]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix a serious issue with CSQC frametime being non-zero on both calls
[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_buffermegs[R_BUFFERDATA_COUNT] =
242 {
243         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
244         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
245         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
246         {CVAR_SAVE, "r_buffermegs_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         CHECKGLERROR
1378 }
1379
1380 #ifdef SUPPORTD3D
1381
1382 #ifdef SUPPORTD3D
1383 #include <d3d9.h>
1384 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1385 extern D3DCAPS9 vid_d3d9caps;
1386 #endif
1387
1388 struct r_hlsl_permutation_s;
1389 typedef struct r_hlsl_permutation_s
1390 {
1391         /// hash lookup data
1392         struct r_hlsl_permutation_s *hashnext;
1393         unsigned int mode;
1394         unsigned int permutation;
1395
1396         /// indicates if we have tried compiling this permutation already
1397         qboolean compiled;
1398         /// NULL if compilation failed
1399         IDirect3DVertexShader9 *vertexshader;
1400         IDirect3DPixelShader9 *pixelshader;
1401 }
1402 r_hlsl_permutation_t;
1403
1404 typedef enum D3DVSREGISTER_e
1405 {
1406         D3DVSREGISTER_TexMatrix = 0, // float4x4
1407         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1408         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1409         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1410         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1411         D3DVSREGISTER_ModelToLight = 20, // float4x4
1412         D3DVSREGISTER_EyePosition = 24,
1413         D3DVSREGISTER_FogPlane = 25,
1414         D3DVSREGISTER_LightDir = 26,
1415         D3DVSREGISTER_LightPosition = 27,
1416 }
1417 D3DVSREGISTER_t;
1418
1419 typedef enum D3DPSREGISTER_e
1420 {
1421         D3DPSREGISTER_Alpha = 0,
1422         D3DPSREGISTER_BloomBlur_Parameters = 1,
1423         D3DPSREGISTER_ClientTime = 2,
1424         D3DPSREGISTER_Color_Ambient = 3,
1425         D3DPSREGISTER_Color_Diffuse = 4,
1426         D3DPSREGISTER_Color_Specular = 5,
1427         D3DPSREGISTER_Color_Glow = 6,
1428         D3DPSREGISTER_Color_Pants = 7,
1429         D3DPSREGISTER_Color_Shirt = 8,
1430         D3DPSREGISTER_DeferredColor_Ambient = 9,
1431         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1432         D3DPSREGISTER_DeferredColor_Specular = 11,
1433         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1434         D3DPSREGISTER_DeferredMod_Specular = 13,
1435         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1436         D3DPSREGISTER_EyePosition = 15, // unused
1437         D3DPSREGISTER_FogColor = 16,
1438         D3DPSREGISTER_FogHeightFade = 17,
1439         D3DPSREGISTER_FogPlane = 18,
1440         D3DPSREGISTER_FogPlaneViewDist = 19,
1441         D3DPSREGISTER_FogRangeRecip = 20,
1442         D3DPSREGISTER_LightColor = 21,
1443         D3DPSREGISTER_LightDir = 22, // unused
1444         D3DPSREGISTER_LightPosition = 23,
1445         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1446         D3DPSREGISTER_PixelSize = 25,
1447         D3DPSREGISTER_ReflectColor = 26,
1448         D3DPSREGISTER_ReflectFactor = 27,
1449         D3DPSREGISTER_ReflectOffset = 28,
1450         D3DPSREGISTER_RefractColor = 29,
1451         D3DPSREGISTER_Saturation = 30,
1452         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1453         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1454         D3DPSREGISTER_ScreenToDepth = 33,
1455         D3DPSREGISTER_ShadowMap_Parameters = 34,
1456         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1457         D3DPSREGISTER_SpecularPower = 36,
1458         D3DPSREGISTER_UserVec1 = 37,
1459         D3DPSREGISTER_UserVec2 = 38,
1460         D3DPSREGISTER_UserVec3 = 39,
1461         D3DPSREGISTER_UserVec4 = 40,
1462         D3DPSREGISTER_ViewTintColor = 41,
1463         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1464         D3DPSREGISTER_BloomColorSubtract = 43,
1465         D3DPSREGISTER_ViewToLight = 44, // float4x4
1466         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1467         D3DPSREGISTER_NormalmapScrollBlend = 52,
1468         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1469         D3DPSREGISTER_OffsetMapping_Bias = 54,
1470         // next at 54
1471 }
1472 D3DPSREGISTER_t;
1473
1474 /// information about each possible shader permutation
1475 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1476 /// currently selected permutation
1477 r_hlsl_permutation_t *r_hlsl_permutation;
1478 /// storage for permutations linked in the hash table
1479 memexpandablearray_t r_hlsl_permutationarray;
1480
1481 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1482 {
1483         //unsigned int hashdepth = 0;
1484         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1485         r_hlsl_permutation_t *p;
1486         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1487         {
1488                 if (p->mode == mode && p->permutation == permutation)
1489                 {
1490                         //if (hashdepth > 10)
1491                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1492                         return p;
1493                 }
1494                 //hashdepth++;
1495         }
1496         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1497         p->mode = mode;
1498         p->permutation = permutation;
1499         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1500         r_hlsl_permutationhash[mode][hashindex] = p;
1501         //if (hashdepth > 10)
1502         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1503         return p;
1504 }
1505
1506 #include <d3dx9.h>
1507 //#include <d3dx9shader.h>
1508 //#include <d3dx9mesh.h>
1509
1510 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1511 {
1512         DWORD *vsbin = NULL;
1513         DWORD *psbin = NULL;
1514         fs_offset_t vsbinsize;
1515         fs_offset_t psbinsize;
1516 //      IDirect3DVertexShader9 *vs = NULL;
1517 //      IDirect3DPixelShader9 *ps = NULL;
1518         ID3DXBuffer *vslog = NULL;
1519         ID3DXBuffer *vsbuffer = NULL;
1520         ID3DXConstantTable *vsconstanttable = NULL;
1521         ID3DXBuffer *pslog = NULL;
1522         ID3DXBuffer *psbuffer = NULL;
1523         ID3DXConstantTable *psconstanttable = NULL;
1524         int vsresult = 0;
1525         int psresult = 0;
1526         char temp[MAX_INPUTLINE];
1527         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1528         char vabuf[1024];
1529         qboolean debugshader = gl_paranoid.integer != 0;
1530         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1531         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1532         if (!debugshader)
1533         {
1534                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1535                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1536         }
1537         if ((!vsbin && vertstring) || (!psbin && fragstring))
1538         {
1539                 const char* dllnames_d3dx9 [] =
1540                 {
1541                         "d3dx9_43.dll",
1542                         "d3dx9_42.dll",
1543                         "d3dx9_41.dll",
1544                         "d3dx9_40.dll",
1545                         "d3dx9_39.dll",
1546                         "d3dx9_38.dll",
1547                         "d3dx9_37.dll",
1548                         "d3dx9_36.dll",
1549                         "d3dx9_35.dll",
1550                         "d3dx9_34.dll",
1551                         "d3dx9_33.dll",
1552                         "d3dx9_32.dll",
1553                         "d3dx9_31.dll",
1554                         "d3dx9_30.dll",
1555                         "d3dx9_29.dll",
1556                         "d3dx9_28.dll",
1557                         "d3dx9_27.dll",
1558                         "d3dx9_26.dll",
1559                         "d3dx9_25.dll",
1560                         "d3dx9_24.dll",
1561                         NULL
1562                 };
1563                 dllhandle_t d3dx9_dll = NULL;
1564                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1565                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1566                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1567                 dllfunction_t d3dx9_dllfuncs[] =
1568                 {
1569                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1570                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1571                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1572                         {NULL, NULL}
1573                 };
1574                 // 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...
1575 #ifndef ID3DXBuffer_GetBufferPointer
1576 #if !defined(__cplusplus) || defined(CINTERFACE)
1577 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1578 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1579 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1580 #else
1581 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1582 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1583 #define ID3DXBuffer_Release(p)            (p)->Release()
1584 #endif
1585 #endif
1586                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1587                 {
1588                         DWORD shaderflags = 0;
1589                         if (debugshader)
1590                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1591                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1592                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1593                         if (vertstring && vertstring[0])
1594                         {
1595                                 if (debugshader)
1596                                 {
1597                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1598                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1599                                 }
1600                                 else
1601                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1602                                 if (vsbuffer)
1603                                 {
1604                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1605                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1606                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1607                                         ID3DXBuffer_Release(vsbuffer);
1608                                 }
1609                                 if (vslog)
1610                                 {
1611                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1612                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1613                                         ID3DXBuffer_Release(vslog);
1614                                 }
1615                         }
1616                         if (fragstring && fragstring[0])
1617                         {
1618                                 if (debugshader)
1619                                 {
1620                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1621                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1622                                 }
1623                                 else
1624                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1625                                 if (psbuffer)
1626                                 {
1627                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1628                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1629                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1630                                         ID3DXBuffer_Release(psbuffer);
1631                                 }
1632                                 if (pslog)
1633                                 {
1634                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1635                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1636                                         ID3DXBuffer_Release(pslog);
1637                                 }
1638                         }
1639                         Sys_UnloadLibrary(&d3dx9_dll);
1640                 }
1641                 else
1642                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1643         }
1644         if (vsbin && psbin)
1645         {
1646                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1647                 if (FAILED(vsresult))
1648                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1649                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1650                 if (FAILED(psresult))
1651                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1652         }
1653         // free the shader data
1654         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1655         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1656 }
1657
1658 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1659 {
1660         int i;
1661         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1662         int vertstring_length = 0;
1663         int geomstring_length = 0;
1664         int fragstring_length = 0;
1665         char *t;
1666         char *sourcestring;
1667         char *vertstring, *geomstring, *fragstring;
1668         char permutationname[256];
1669         char cachename[256];
1670         int vertstrings_count = 0;
1671         int geomstrings_count = 0;
1672         int fragstrings_count = 0;
1673         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1674         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1675         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1676
1677         if (p->compiled)
1678                 return;
1679         p->compiled = true;
1680         p->vertexshader = NULL;
1681         p->pixelshader = NULL;
1682
1683         permutationname[0] = 0;
1684         cachename[0] = 0;
1685         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1686
1687         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1688         strlcat(cachename, "hlsl/", sizeof(cachename));
1689
1690         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1691         vertstrings_count = 0;
1692         geomstrings_count = 0;
1693         fragstrings_count = 0;
1694         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1695         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1696         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1697
1698         // the first pretext is which type of shader to compile as
1699         // (later these will all be bound together as a program object)
1700         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1701         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1702         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1703
1704         // the second pretext is the mode (for example a light source)
1705         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1706         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1707         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1708         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1709         strlcat(cachename, modeinfo->name, sizeof(cachename));
1710
1711         // now add all the permutation pretexts
1712         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1713         {
1714                 if (permutation & (1<<i))
1715                 {
1716                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1717                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1718                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1719                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1720                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1721                 }
1722                 else
1723                 {
1724                         // keep line numbers correct
1725                         vertstrings_list[vertstrings_count++] = "\n";
1726                         geomstrings_list[geomstrings_count++] = "\n";
1727                         fragstrings_list[fragstrings_count++] = "\n";
1728                 }
1729         }
1730
1731         // add static parms
1732         R_CompileShader_AddStaticParms(mode, permutation);
1733         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1734         vertstrings_count += shaderstaticparms_count;
1735         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1736         geomstrings_count += shaderstaticparms_count;
1737         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1738         fragstrings_count += shaderstaticparms_count;
1739
1740         // replace spaces in the cachename with _ characters
1741         for (i = 0;cachename[i];i++)
1742                 if (cachename[i] == ' ')
1743                         cachename[i] = '_';
1744
1745         // now append the shader text itself
1746         vertstrings_list[vertstrings_count++] = sourcestring;
1747         geomstrings_list[geomstrings_count++] = sourcestring;
1748         fragstrings_list[fragstrings_count++] = sourcestring;
1749
1750         vertstring_length = 0;
1751         for (i = 0;i < vertstrings_count;i++)
1752                 vertstring_length += strlen(vertstrings_list[i]);
1753         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1754         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1755                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1756
1757         geomstring_length = 0;
1758         for (i = 0;i < geomstrings_count;i++)
1759                 geomstring_length += strlen(geomstrings_list[i]);
1760         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1761         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1762                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1763
1764         fragstring_length = 0;
1765         for (i = 0;i < fragstrings_count;i++)
1766                 fragstring_length += strlen(fragstrings_list[i]);
1767         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1768         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1769                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1770
1771         // try to load the cached shader, or generate one
1772         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1773
1774         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1775                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1776         else
1777                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1778
1779         // free the strings
1780         if (vertstring)
1781                 Mem_Free(vertstring);
1782         if (geomstring)
1783                 Mem_Free(geomstring);
1784         if (fragstring)
1785                 Mem_Free(fragstring);
1786         if (sourcestring)
1787                 Mem_Free(sourcestring);
1788 }
1789
1790 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1791 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1792 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);}
1793 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);}
1794 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);}
1795 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);}
1796
1797 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1798 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1799 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);}
1800 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);}
1801 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);}
1802 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);}
1803
1804 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1805 {
1806         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1807         if (r_hlsl_permutation != perm)
1808         {
1809                 r_hlsl_permutation = perm;
1810                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1811                 {
1812                         if (!r_hlsl_permutation->compiled)
1813                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1814                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1815                         {
1816                                 // remove features until we find a valid permutation
1817                                 int i;
1818                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1819                                 {
1820                                         // reduce i more quickly whenever it would not remove any bits
1821                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1822                                         if (!(permutation & j))
1823                                                 continue;
1824                                         permutation -= j;
1825                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1826                                         if (!r_hlsl_permutation->compiled)
1827                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1828                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1829                                                 break;
1830                                 }
1831                                 if (i >= SHADERPERMUTATION_COUNT)
1832                                 {
1833                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1834                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1835                                         return; // no bit left to clear, entire mode is broken
1836                                 }
1837                         }
1838                 }
1839                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1840                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1841         }
1842         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1843         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1844         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1845 }
1846 #endif
1847
1848 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1849 {
1850         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1851         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1852         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1853         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1854 }
1855
1856 void R_GLSL_Restart_f(void)
1857 {
1858         unsigned int i, limit;
1859         if (glslshaderstring)
1860                 Mem_Free(glslshaderstring);
1861         glslshaderstring = NULL;
1862         if (hlslshaderstring)
1863                 Mem_Free(hlslshaderstring);
1864         hlslshaderstring = NULL;
1865         switch(vid.renderpath)
1866         {
1867         case RENDERPATH_D3D9:
1868 #ifdef SUPPORTD3D
1869                 {
1870                         r_hlsl_permutation_t *p;
1871                         r_hlsl_permutation = NULL;
1872                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1873                         for (i = 0;i < limit;i++)
1874                         {
1875                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1876                                 {
1877                                         if (p->vertexshader)
1878                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1879                                         if (p->pixelshader)
1880                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1881                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1882                                 }
1883                         }
1884                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1885                 }
1886 #endif
1887                 break;
1888         case RENDERPATH_D3D10:
1889                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1890                 break;
1891         case RENDERPATH_D3D11:
1892                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1893                 break;
1894         case RENDERPATH_GL20:
1895         case RENDERPATH_GLES2:
1896                 {
1897                         r_glsl_permutation_t *p;
1898                         r_glsl_permutation = NULL;
1899                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1900                         for (i = 0;i < limit;i++)
1901                         {
1902                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1903                                 {
1904                                         GL_Backend_FreeProgram(p->program);
1905                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1906                                 }
1907                         }
1908                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1909                 }
1910                 break;
1911         case RENDERPATH_GL11:
1912         case RENDERPATH_GL13:
1913         case RENDERPATH_GLES1:
1914                 break;
1915         case RENDERPATH_SOFT:
1916                 break;
1917         }
1918 }
1919
1920 static void R_GLSL_DumpShader_f(void)
1921 {
1922         int i, language, mode, dupe;
1923         char *text;
1924         shadermodeinfo_t *modeinfo;
1925         qfile_t *file;
1926
1927         for (language = 0;language < 2;language++)
1928         {
1929                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1930                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1931                 {
1932                         // don't dump the same file multiple times (most or all shaders come from the same file)
1933                         for (dupe = mode - 1;dupe >= 0;dupe--)
1934                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1935                                         break;
1936                         if (dupe >= 0)
1937                                 continue;
1938                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1939                         if (!text)
1940                                 continue;
1941                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1942                         if (file)
1943                         {
1944                                 FS_Print(file, "/* The engine may define the following macros:\n");
1945                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1946                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1947                                         FS_Print(file, modeinfo[i].pretext);
1948                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1949                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1950                                 FS_Print(file, "*/\n");
1951                                 FS_Print(file, text);
1952                                 FS_Close(file);
1953                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1954                         }
1955                         else
1956                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1957                         Mem_Free(text);
1958                 }
1959         }
1960 }
1961
1962 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1963 {
1964         unsigned int permutation = 0;
1965         if (r_trippy.integer && !notrippy)
1966                 permutation |= SHADERPERMUTATION_TRIPPY;
1967         permutation |= SHADERPERMUTATION_VIEWTINT;
1968         if (first)
1969                 permutation |= SHADERPERMUTATION_DIFFUSE;
1970         if (second)
1971                 permutation |= SHADERPERMUTATION_SPECULAR;
1972         if (texturemode == GL_MODULATE)
1973                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1974         else if (texturemode == GL_ADD)
1975                 permutation |= SHADERPERMUTATION_GLOW;
1976         else if (texturemode == GL_DECAL)
1977                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1978         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1979                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1980         if (suppresstexalpha)
1981                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1982         if (!second)
1983                 texturemode = GL_MODULATE;
1984         if (vid.allowalphatocoverage)
1985                 GL_AlphaToCoverage(false);
1986         switch (vid.renderpath)
1987         {
1988         case RENDERPATH_D3D9:
1989 #ifdef SUPPORTD3D
1990                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1991                 R_Mesh_TexBind(GL20TU_FIRST , first );
1992                 R_Mesh_TexBind(GL20TU_SECOND, second);
1993                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1994                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1995 #endif
1996                 break;
1997         case RENDERPATH_D3D10:
1998                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1999                 break;
2000         case RENDERPATH_D3D11:
2001                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2002                 break;
2003         case RENDERPATH_GL20:
2004         case RENDERPATH_GLES2:
2005                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2006                 if (r_glsl_permutation->tex_Texture_First >= 0)
2007                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2008                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2009                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2010                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2011                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2012                 break;
2013         case RENDERPATH_GL13:
2014         case RENDERPATH_GLES1:
2015                 R_Mesh_TexBind(0, first );
2016                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2017                 R_Mesh_TexMatrix(0, NULL);
2018                 R_Mesh_TexBind(1, second);
2019                 if (second)
2020                 {
2021                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2022                         R_Mesh_TexMatrix(1, NULL);
2023                 }
2024                 break;
2025         case RENDERPATH_GL11:
2026                 R_Mesh_TexBind(0, first );
2027                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2028                 R_Mesh_TexMatrix(0, NULL);
2029                 break;
2030         case RENDERPATH_SOFT:
2031                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2032                 R_Mesh_TexBind(GL20TU_FIRST , first );
2033                 R_Mesh_TexBind(GL20TU_SECOND, second);
2034                 break;
2035         }
2036 }
2037
2038 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2039 {
2040         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2041 }
2042
2043 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2044 {
2045         unsigned int permutation = 0;
2046         if (r_trippy.integer && !notrippy)
2047                 permutation |= SHADERPERMUTATION_TRIPPY;
2048         if (depthrgb)
2049                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2050         if (skeletal)
2051                 permutation |= SHADERPERMUTATION_SKELETAL;
2052
2053         if (vid.allowalphatocoverage)
2054                 GL_AlphaToCoverage(false);
2055         switch (vid.renderpath)
2056         {
2057         case RENDERPATH_D3D9:
2058 #ifdef SUPPORTD3D
2059                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2060 #endif
2061                 break;
2062         case RENDERPATH_D3D10:
2063                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2064                 break;
2065         case RENDERPATH_D3D11:
2066                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2067                 break;
2068         case RENDERPATH_GL20:
2069         case RENDERPATH_GLES2:
2070                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2071                 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);
2072                 break;
2073         case RENDERPATH_GL13:
2074         case RENDERPATH_GLES1:
2075                 R_Mesh_TexBind(0, 0);
2076                 R_Mesh_TexBind(1, 0);
2077                 break;
2078         case RENDERPATH_GL11:
2079                 R_Mesh_TexBind(0, 0);
2080                 break;
2081         case RENDERPATH_SOFT:
2082                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2083                 break;
2084         }
2085 }
2086
2087 extern qboolean r_shadow_usingdeferredprepass;
2088 extern rtexture_t *r_shadow_attenuationgradienttexture;
2089 extern rtexture_t *r_shadow_attenuation2dtexture;
2090 extern rtexture_t *r_shadow_attenuation3dtexture;
2091 extern qboolean r_shadow_usingshadowmap2d;
2092 extern qboolean r_shadow_usingshadowmaportho;
2093 extern float r_shadow_shadowmap_texturescale[2];
2094 extern float r_shadow_shadowmap_parameters[4];
2095 extern qboolean r_shadow_shadowmapvsdct;
2096 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2097 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2098 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2099 extern matrix4x4_t r_shadow_shadowmapmatrix;
2100 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2101 extern int r_shadow_prepass_width;
2102 extern int r_shadow_prepass_height;
2103 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2104 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2105 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2106 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2107
2108 #define BLENDFUNC_ALLOWS_COLORMOD      1
2109 #define BLENDFUNC_ALLOWS_FOG           2
2110 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2111 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2112 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2113 static int R_BlendFuncFlags(int src, int dst)
2114 {
2115         int r = 0;
2116
2117         // a blendfunc allows colormod if:
2118         // a) it can never keep the destination pixel invariant, or
2119         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2120         // this is to prevent unintended side effects from colormod
2121
2122         // a blendfunc allows fog if:
2123         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2124         // this is to prevent unintended side effects from fog
2125
2126         // these checks are the output of fogeval.pl
2127
2128         r |= BLENDFUNC_ALLOWS_COLORMOD;
2129         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2130         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2131         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2132         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2133         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2134         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2135         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2136         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2137         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2138         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2139         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2140         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2141         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2142         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2143         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2144         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2145         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2146         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2147         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2148         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2149         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2150
2151         return r;
2152 }
2153
2154 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)
2155 {
2156         // select a permutation of the lighting shader appropriate to this
2157         // combination of texture, entity, light source, and fogging, only use the
2158         // minimum features necessary to avoid wasting rendering time in the
2159         // fragment shader on features that are not being used
2160         unsigned int permutation = 0;
2161         unsigned int mode = 0;
2162         int blendfuncflags;
2163         static float dummy_colormod[3] = {1, 1, 1};
2164         float *colormod = rsurface.colormod;
2165         float m16f[16];
2166         matrix4x4_t tempmatrix;
2167         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2168         if (r_trippy.integer && !notrippy)
2169                 permutation |= SHADERPERMUTATION_TRIPPY;
2170         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2171                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2172         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2173                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2174         if (rsurfacepass == RSURFPASS_BACKGROUND)
2175         {
2176                 // distorted background
2177                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2178                 {
2179                         mode = SHADERMODE_WATER;
2180                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2181                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2182                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2183                         {
2184                                 // this is the right thing to do for wateralpha
2185                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2186                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2187                         }
2188                         else
2189                         {
2190                                 // this is the right thing to do for entity alpha
2191                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2192                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2193                         }
2194                 }
2195                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2196                 {
2197                         mode = SHADERMODE_REFRACTION;
2198                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2199                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2200                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2201                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2202                 }
2203                 else
2204                 {
2205                         mode = SHADERMODE_GENERIC;
2206                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2207                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2208                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2209                 }
2210                 if (vid.allowalphatocoverage)
2211                         GL_AlphaToCoverage(false);
2212         }
2213         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2214         {
2215                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2216                 {
2217                         switch(rsurface.texture->offsetmapping)
2218                         {
2219                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2220                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2221                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2222                         case OFFSETMAPPING_OFF: break;
2223                         }
2224                 }
2225                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2226                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2227                 // normalmap (deferred prepass), may use alpha test on diffuse
2228                 mode = SHADERMODE_DEFERREDGEOMETRY;
2229                 GL_BlendFunc(GL_ONE, GL_ZERO);
2230                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2231                 if (vid.allowalphatocoverage)
2232                         GL_AlphaToCoverage(false);
2233         }
2234         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2235         {
2236                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2237                 {
2238                         switch(rsurface.texture->offsetmapping)
2239                         {
2240                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2241                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2242                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2243                         case OFFSETMAPPING_OFF: break;
2244                         }
2245                 }
2246                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2247                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2248                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2249                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2250                 // light source
2251                 mode = SHADERMODE_LIGHTSOURCE;
2252                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2253                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2254                 if (diffusescale > 0)
2255                         permutation |= SHADERPERMUTATION_DIFFUSE;
2256                 if (specularscale > 0)
2257                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2258                 if (r_refdef.fogenabled)
2259                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2260                 if (rsurface.texture->colormapping)
2261                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2262                 if (r_shadow_usingshadowmap2d)
2263                 {
2264                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2265                         if(r_shadow_shadowmapvsdct)
2266                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2267
2268                         if (r_shadow_shadowmap2ddepthbuffer)
2269                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2270                 }
2271                 if (rsurface.texture->reflectmasktexture)
2272                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2273                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2274                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2275                 if (vid.allowalphatocoverage)
2276                         GL_AlphaToCoverage(false);
2277         }
2278         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2279         {
2280                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2281                 {
2282                         switch(rsurface.texture->offsetmapping)
2283                         {
2284                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2285                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2287                         case OFFSETMAPPING_OFF: break;
2288                         }
2289                 }
2290                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2291                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2292                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2293                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2294                 // unshaded geometry (fullbright or ambient model lighting)
2295                 mode = SHADERMODE_FLATCOLOR;
2296                 ambientscale = diffusescale = specularscale = 0;
2297                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2298                         permutation |= SHADERPERMUTATION_GLOW;
2299                 if (r_refdef.fogenabled)
2300                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2301                 if (rsurface.texture->colormapping)
2302                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2303                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2304                 {
2305                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2306                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2307
2308                         if (r_shadow_shadowmap2ddepthbuffer)
2309                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2310                 }
2311                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2312                         permutation |= SHADERPERMUTATION_REFLECTION;
2313                 if (rsurface.texture->reflectmasktexture)
2314                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2315                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2316                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2317                 // when using alphatocoverage, we don't need alphakill
2318                 if (vid.allowalphatocoverage)
2319                 {
2320                         if (r_transparent_alphatocoverage.integer)
2321                         {
2322                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2323                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2324                         }
2325                         else
2326                                 GL_AlphaToCoverage(false);
2327                 }
2328         }
2329         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2330         {
2331                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2332                 {
2333                         switch(rsurface.texture->offsetmapping)
2334                         {
2335                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2336                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2337                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2338                         case OFFSETMAPPING_OFF: break;
2339                         }
2340                 }
2341                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2342                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2343                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2344                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2345                 // directional model lighting
2346                 mode = SHADERMODE_LIGHTDIRECTION;
2347                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2348                         permutation |= SHADERPERMUTATION_GLOW;
2349                 permutation |= SHADERPERMUTATION_DIFFUSE;
2350                 if (specularscale > 0)
2351                         permutation |= SHADERPERMUTATION_SPECULAR;
2352                 if (r_refdef.fogenabled)
2353                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2354                 if (rsurface.texture->colormapping)
2355                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2356                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2357                 {
2358                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2359                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2360
2361                         if (r_shadow_shadowmap2ddepthbuffer)
2362                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2363                 }
2364                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2365                         permutation |= SHADERPERMUTATION_REFLECTION;
2366                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2367                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2368                 if (rsurface.texture->reflectmasktexture)
2369                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2370                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2371                 {
2372                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2373                         if (r_shadow_bouncegriddirectional)
2374                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2375                 }
2376                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2377                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2378                 // when using alphatocoverage, we don't need alphakill
2379                 if (vid.allowalphatocoverage)
2380                 {
2381                         if (r_transparent_alphatocoverage.integer)
2382                         {
2383                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2384                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2385                         }
2386                         else
2387                                 GL_AlphaToCoverage(false);
2388                 }
2389         }
2390         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2391         {
2392                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2393                 {
2394                         switch(rsurface.texture->offsetmapping)
2395                         {
2396                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2397                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2398                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2399                         case OFFSETMAPPING_OFF: break;
2400                         }
2401                 }
2402                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2403                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2404                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2405                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2406                 // ambient model lighting
2407                 mode = SHADERMODE_LIGHTDIRECTION;
2408                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2409                         permutation |= SHADERPERMUTATION_GLOW;
2410                 if (r_refdef.fogenabled)
2411                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2412                 if (rsurface.texture->colormapping)
2413                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2414                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2415                 {
2416                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2417                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2418
2419                         if (r_shadow_shadowmap2ddepthbuffer)
2420                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2421                 }
2422                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2423                         permutation |= SHADERPERMUTATION_REFLECTION;
2424                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2425                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2426                 if (rsurface.texture->reflectmasktexture)
2427                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2428                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2429                 {
2430                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2431                         if (r_shadow_bouncegriddirectional)
2432                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2433                 }
2434                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2435                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2436                 // when using alphatocoverage, we don't need alphakill
2437                 if (vid.allowalphatocoverage)
2438                 {
2439                         if (r_transparent_alphatocoverage.integer)
2440                         {
2441                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2442                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2443                         }
2444                         else
2445                                 GL_AlphaToCoverage(false);
2446                 }
2447         }
2448         else
2449         {
2450                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2451                 {
2452                         switch(rsurface.texture->offsetmapping)
2453                         {
2454                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2455                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2456                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2457                         case OFFSETMAPPING_OFF: break;
2458                         }
2459                 }
2460                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2461                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2462                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2463                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2464                 // lightmapped wall
2465                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2466                         permutation |= SHADERPERMUTATION_GLOW;
2467                 if (r_refdef.fogenabled)
2468                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2469                 if (rsurface.texture->colormapping)
2470                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2471                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2472                 {
2473                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2474                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2475
2476                         if (r_shadow_shadowmap2ddepthbuffer)
2477                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2478                 }
2479                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2480                         permutation |= SHADERPERMUTATION_REFLECTION;
2481                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2482                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2483                 if (rsurface.texture->reflectmasktexture)
2484                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2485                 if (FAKELIGHT_ENABLED)
2486                 {
2487                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2488                         mode = SHADERMODE_FAKELIGHT;
2489                         permutation |= SHADERPERMUTATION_DIFFUSE;
2490                         if (specularscale > 0)
2491                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2492                 }
2493                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2494                 {
2495                         // deluxemapping (light direction texture)
2496                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2497                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2498                         else
2499                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2500                         permutation |= SHADERPERMUTATION_DIFFUSE;
2501                         if (specularscale > 0)
2502                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2503                 }
2504                 else if (r_glsl_deluxemapping.integer >= 2)
2505                 {
2506                         // fake deluxemapping (uniform light direction in tangentspace)
2507                         if (rsurface.uselightmaptexture)
2508                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2509                         else
2510                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2511                         permutation |= SHADERPERMUTATION_DIFFUSE;
2512                         if (specularscale > 0)
2513                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2514                 }
2515                 else if (rsurface.uselightmaptexture)
2516                 {
2517                         // ordinary lightmapping (q1bsp, q3bsp)
2518                         mode = SHADERMODE_LIGHTMAP;
2519                 }
2520                 else
2521                 {
2522                         // ordinary vertex coloring (q3bsp)
2523                         mode = SHADERMODE_VERTEXCOLOR;
2524                 }
2525                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2526                 {
2527                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2528                         if (r_shadow_bouncegriddirectional)
2529                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2530                 }
2531                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2532                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2533                 // when using alphatocoverage, we don't need alphakill
2534                 if (vid.allowalphatocoverage)
2535                 {
2536                         if (r_transparent_alphatocoverage.integer)
2537                         {
2538                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2539                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2540                         }
2541                         else
2542                                 GL_AlphaToCoverage(false);
2543                 }
2544         }
2545         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2546                 colormod = dummy_colormod;
2547         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2548                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2549         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2550                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2551         switch(vid.renderpath)
2552         {
2553         case RENDERPATH_D3D9:
2554 #ifdef SUPPORTD3D
2555                 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);
2556                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2557                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2558                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2559                 if (mode == SHADERMODE_LIGHTSOURCE)
2560                 {
2561                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2562                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2563                 }
2564                 else
2565                 {
2566                         if (mode == SHADERMODE_LIGHTDIRECTION)
2567                         {
2568                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2569                         }
2570                 }
2571                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2572                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2573                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2574                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2575                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2576
2577                 if (mode == SHADERMODE_LIGHTSOURCE)
2578                 {
2579                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2580                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2581                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2582                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2583                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2584
2585                         // additive passes are only darkened by fog, not tinted
2586                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2587                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2588                 }
2589                 else
2590                 {
2591                         if (mode == SHADERMODE_FLATCOLOR)
2592                         {
2593                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2594                         }
2595                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2596                         {
2597                                 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]);
2598                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2599                                 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);
2600                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2601                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2602                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2603                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2604                         }
2605                         else
2606                         {
2607                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2608                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2609                                 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);
2610                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2611                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2612                         }
2613                         // additive passes are only darkened by fog, not tinted
2614                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2615                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2616                         else
2617                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2618                         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);
2619                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2620                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2621                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2622                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2623                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2624                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2625                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2626                         if (mode == SHADERMODE_WATER)
2627                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2628                 }
2629                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2630                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2631                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2632                 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));
2633                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2634                 if (rsurface.texture->pantstexture)
2635                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2636                 else
2637                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2638                 if (rsurface.texture->shirttexture)
2639                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2640                 else
2641                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2642                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2643                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2644                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2645                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2646                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2647                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2648                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2649                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2650                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2651                         );
2652                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2653                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2654                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2655                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2656
2657                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2658                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2659                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2660                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2661                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2662                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2663                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2664                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2665                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2666                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2667                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2668                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2669                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2670                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2671                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2672                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2673                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2674                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2675                 {
2676                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2677                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2678                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2679                 }
2680                 else
2681                 {
2682                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2683                 }
2684 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2685                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2686                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2687                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2688                 {
2689                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2690                         if (rsurface.rtlight)
2691                         {
2692                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2693                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2694                         }
2695                 }
2696 #endif
2697                 break;
2698         case RENDERPATH_D3D10:
2699                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2700                 break;
2701         case RENDERPATH_D3D11:
2702                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2703                 break;
2704         case RENDERPATH_GL20:
2705         case RENDERPATH_GLES2:
2706                 if (!vid.useinterleavedarrays)
2707                 {
2708                         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);
2709                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2710                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2711                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2712                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2713                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2714                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2715                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2716                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2717                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2718                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2719                 }
2720                 else
2721                 {
2722                         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);
2723                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2724                 }
2725                 // this has to be after RSurf_PrepareVerticesForBatch
2726                 if (rsurface.batchskeletaltransform3x4buffer)
2727                         permutation |= SHADERPERMUTATION_SKELETAL;
2728                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2729                 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);
2730                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2731                 if (mode == SHADERMODE_LIGHTSOURCE)
2732                 {
2733                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2734                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2735                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2736                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2737                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2738                         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);
2739         
2740                         // additive passes are only darkened by fog, not tinted
2741                         if (r_glsl_permutation->loc_FogColor >= 0)
2742                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2743                         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);
2744                 }
2745                 else
2746                 {
2747                         if (mode == SHADERMODE_FLATCOLOR)
2748                         {
2749                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2750                         }
2751                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2752                         {
2753                                 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]);
2754                                 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]);
2755                                 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);
2756                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2757                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2758                                 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]);
2759                                 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]);
2760                         }
2761                         else
2762                         {
2763                                 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]);
2764                                 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]);
2765                                 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);
2766                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2767                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2768                         }
2769                         // additive passes are only darkened by fog, not tinted
2770                         if (r_glsl_permutation->loc_FogColor >= 0)
2771                         {
2772                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2773                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2774                                 else
2775                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2776                         }
2777                         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);
2778                         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]);
2779                         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]);
2780                         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]);
2781                         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]);
2782                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2783                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2784                         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);
2785                         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]);
2786                 }
2787                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2788                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2789                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2790                 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]);
2791                 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]);
2792
2793                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2794                 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));
2795                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2796                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2797                 {
2798                         if (rsurface.texture->pantstexture)
2799                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2800                         else
2801                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2802                 }
2803                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2804                 {
2805                         if (rsurface.texture->shirttexture)
2806                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2807                         else
2808                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2809                 }
2810                 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]);
2811                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2812                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2813                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2814                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2815                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2816                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2817                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2818                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2819                         );
2820                 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);
2821                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2822                 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]);
2823                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2824                 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);}
2825                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2826
2827                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2828                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2829                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2830                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2831                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2832                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2833                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2834                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2835                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2836                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2837                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2838                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2839                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2840                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2841                 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);
2842                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2843                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2844                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2845                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2846                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2847                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2848                 {
2849                         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);
2850                         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);
2851                         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);
2852                 }
2853                 else
2854                 {
2855                         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);
2856                 }
2857                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2858                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2859                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2860                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2861                 {
2862                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2863                         if (rsurface.rtlight)
2864                         {
2865                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2866                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2867                         }
2868                 }
2869                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2870                 CHECKGLERROR
2871                 break;
2872         case RENDERPATH_GL11:
2873         case RENDERPATH_GL13:
2874         case RENDERPATH_GLES1:
2875                 break;
2876         case RENDERPATH_SOFT:
2877                 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);
2878                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2879                 R_SetupShader_SetPermutationSoft(mode, permutation);
2880                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2881                 if (mode == SHADERMODE_LIGHTSOURCE)
2882                 {
2883                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2884                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2885                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2886                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2887                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2888                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2889         
2890                         // additive passes are only darkened by fog, not tinted
2891                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2892                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2893                 }
2894                 else
2895                 {
2896                         if (mode == SHADERMODE_FLATCOLOR)
2897                         {
2898                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2899                         }
2900                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2901                         {
2902                                 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]);
2903                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2904                                 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);
2905                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2906                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2907                                 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]);
2908                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2909                         }
2910                         else
2911                         {
2912                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2913                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2914                                 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);
2915                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2916                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2917                         }
2918                         // additive passes are only darkened by fog, not tinted
2919                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2920                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2921                         else
2922                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2923                         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);
2924                         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]);
2925                         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]);
2926                         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]);
2927                         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]);
2928                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2929                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2930                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2931                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2932                 }
2933                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2934                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2935                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2936                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2937                 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]);
2938
2939                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2940                 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));
2941                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2942                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2943                 {
2944                         if (rsurface.texture->pantstexture)
2945                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2946                         else
2947                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2948                 }
2949                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2950                 {
2951                         if (rsurface.texture->shirttexture)
2952                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2953                         else
2954                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2955                 }
2956                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2957                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2958                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2959                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2960                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2961                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2962                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2963                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2964                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2965                         );
2966                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2967                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2968                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2969                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2970
2971                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2972                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2973                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2974                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2975                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2976                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2977                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2978                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2979                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2980                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2981                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2982                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2983                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2984                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2985                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2986                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2987                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2988                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2989                 {
2990                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2991                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2992                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2993                 }
2994                 else
2995                 {
2996                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2997                 }
2998 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2999                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3000                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3001                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3002                 {
3003                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3004                         if (rsurface.rtlight)
3005                         {
3006                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3007                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3008                         }
3009                 }
3010                 break;
3011         }
3012 }
3013
3014 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3015 {
3016         // select a permutation of the lighting shader appropriate to this
3017         // combination of texture, entity, light source, and fogging, only use the
3018         // minimum features necessary to avoid wasting rendering time in the
3019         // fragment shader on features that are not being used
3020         unsigned int permutation = 0;
3021         unsigned int mode = 0;
3022         const float *lightcolorbase = rtlight->currentcolor;
3023         float ambientscale = rtlight->ambientscale;
3024         float diffusescale = rtlight->diffusescale;
3025         float specularscale = rtlight->specularscale;
3026         // this is the location of the light in view space
3027         vec3_t viewlightorigin;
3028         // this transforms from view space (camera) to light space (cubemap)
3029         matrix4x4_t viewtolight;
3030         matrix4x4_t lighttoview;
3031         float viewtolight16f[16];
3032         // light source
3033         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3034         if (rtlight->currentcubemap != r_texture_whitecube)
3035                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3036         if (diffusescale > 0)
3037                 permutation |= SHADERPERMUTATION_DIFFUSE;
3038         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3039                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3040         if (r_shadow_usingshadowmap2d)
3041         {
3042                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3043                 if (r_shadow_shadowmapvsdct)
3044                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3045
3046                 if (r_shadow_shadowmap2ddepthbuffer)
3047                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3048         }
3049         if (vid.allowalphatocoverage)
3050                 GL_AlphaToCoverage(false);
3051         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3052         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3053         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3054         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3055         switch(vid.renderpath)
3056         {
3057         case RENDERPATH_D3D9:
3058 #ifdef SUPPORTD3D
3059                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3060                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3061                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3062                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3063                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3064                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3065                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3066                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3067                 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);
3068                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3069                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3070
3071                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3072                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3073                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3074                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3075                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3076 #endif
3077                 break;
3078         case RENDERPATH_D3D10:
3079                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3080                 break;
3081         case RENDERPATH_D3D11:
3082                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3083                 break;
3084         case RENDERPATH_GL20:
3085         case RENDERPATH_GLES2:
3086                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3087                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3088                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3089                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3090                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3091                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3092                 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]);
3093                 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]);
3094                 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);
3095                 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]);
3096                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3097
3098                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3099                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3100                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3101                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3102                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3103                 break;
3104         case RENDERPATH_GL11:
3105         case RENDERPATH_GL13:
3106         case RENDERPATH_GLES1:
3107                 break;
3108         case RENDERPATH_SOFT:
3109                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3110                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3111                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3112                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3113                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3114                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3115                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3116                 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]);
3117                 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);
3118                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3119                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3120
3121                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3122                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3123                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3124                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3125                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3126                 break;
3127         }
3128 }
3129
3130 #define SKINFRAME_HASH 1024
3131
3132 typedef struct
3133 {
3134         int loadsequence; // incremented each level change
3135         memexpandablearray_t array;
3136         skinframe_t *hash[SKINFRAME_HASH];
3137 }
3138 r_skinframe_t;
3139 r_skinframe_t r_skinframe;
3140
3141 void R_SkinFrame_PrepareForPurge(void)
3142 {
3143         r_skinframe.loadsequence++;
3144         // wrap it without hitting zero
3145         if (r_skinframe.loadsequence >= 200)
3146                 r_skinframe.loadsequence = 1;
3147 }
3148
3149 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3150 {
3151         if (!skinframe)
3152                 return;
3153         // mark the skinframe as used for the purging code
3154         skinframe->loadsequence = r_skinframe.loadsequence;
3155 }
3156
3157 void R_SkinFrame_Purge(void)
3158 {
3159         int i;
3160         skinframe_t *s;
3161         for (i = 0;i < SKINFRAME_HASH;i++)
3162         {
3163                 for (s = r_skinframe.hash[i];s;s = s->next)
3164                 {
3165                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3166                         {
3167                                 if (s->merged == s->base)
3168                                         s->merged = NULL;
3169                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3170                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3171                                 R_PurgeTexture(s->merged);s->merged = NULL;
3172                                 R_PurgeTexture(s->base  );s->base   = NULL;
3173                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3174                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3175                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3176                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3177                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3178                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3179                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3180                                 s->loadsequence = 0;
3181                         }
3182                 }
3183         }
3184 }
3185
3186 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3187         skinframe_t *item;
3188         char basename[MAX_QPATH];
3189
3190         Image_StripImageExtension(name, basename, sizeof(basename));
3191
3192         if( last == NULL ) {
3193                 int hashindex;
3194                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3195                 item = r_skinframe.hash[hashindex];
3196         } else {
3197                 item = last->next;
3198         }
3199
3200         // linearly search through the hash bucket
3201         for( ; item ; item = item->next ) {
3202                 if( !strcmp( item->basename, basename ) ) {
3203                         return item;
3204                 }
3205         }
3206         return NULL;
3207 }
3208
3209 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3210 {
3211         skinframe_t *item;
3212         int hashindex;
3213         char basename[MAX_QPATH];
3214
3215         Image_StripImageExtension(name, basename, sizeof(basename));
3216
3217         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3218         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3219                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3220                         break;
3221
3222         if (!item) {
3223                 rtexture_t *dyntexture;
3224                 // check whether its a dynamic texture
3225                 dyntexture = CL_GetDynTexture( basename );
3226                 if (!add && !dyntexture)
3227                         return NULL;
3228                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3229                 memset(item, 0, sizeof(*item));
3230                 strlcpy(item->basename, basename, sizeof(item->basename));
3231                 item->base = dyntexture; // either NULL or dyntexture handle
3232                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3233                 item->comparewidth = comparewidth;
3234                 item->compareheight = compareheight;
3235                 item->comparecrc = comparecrc;
3236                 item->next = r_skinframe.hash[hashindex];
3237                 r_skinframe.hash[hashindex] = item;
3238         }
3239         else if (textureflags & TEXF_FORCE_RELOAD)
3240         {
3241                 rtexture_t *dyntexture;
3242                 // check whether its a dynamic texture
3243                 dyntexture = CL_GetDynTexture( basename );
3244                 if (!add && !dyntexture)
3245                         return NULL;
3246                 if (item->merged == item->base)
3247                         item->merged = NULL;
3248                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3249                 R_PurgeTexture(item->stain );item->stain  = NULL;
3250                 R_PurgeTexture(item->merged);item->merged = NULL;
3251                 R_PurgeTexture(item->base  );item->base   = NULL;
3252                 R_PurgeTexture(item->pants );item->pants  = NULL;
3253                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3254                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3255                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3256                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3257                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3258         R_PurgeTexture(item->reflect);item->reflect = NULL;
3259                 item->loadsequence = 0;
3260         }
3261         else if( item->base == NULL )
3262         {
3263                 rtexture_t *dyntexture;
3264                 // check whether its a dynamic texture
3265                 // 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]
3266                 dyntexture = CL_GetDynTexture( basename );
3267                 item->base = dyntexture; // either NULL or dyntexture handle
3268         }
3269
3270         R_SkinFrame_MarkUsed(item);
3271         return item;
3272 }
3273
3274 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3275         { \
3276                 unsigned long long avgcolor[5], wsum; \
3277                 int pix, comp, w; \
3278                 avgcolor[0] = 0; \
3279                 avgcolor[1] = 0; \
3280                 avgcolor[2] = 0; \
3281                 avgcolor[3] = 0; \
3282                 avgcolor[4] = 0; \
3283                 wsum = 0; \
3284                 for(pix = 0; pix < cnt; ++pix) \
3285                 { \
3286                         w = 0; \
3287                         for(comp = 0; comp < 3; ++comp) \
3288                                 w += getpixel; \
3289                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3290                         { \
3291                                 ++wsum; \
3292                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3293                                 w = getpixel; \
3294                                 for(comp = 0; comp < 3; ++comp) \
3295                                         avgcolor[comp] += getpixel * w; \
3296                                 avgcolor[3] += w; \
3297                         } \
3298                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3299                         avgcolor[4] += getpixel; \
3300                 } \
3301                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3302                         avgcolor[3] = 1; \
3303                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3304                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3305                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3306                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3307         }
3308
3309 extern cvar_t gl_picmip;
3310 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3311 {
3312         int j;
3313         unsigned char *pixels;
3314         unsigned char *bumppixels;
3315         unsigned char *basepixels = NULL;
3316         int basepixels_width = 0;
3317         int basepixels_height = 0;
3318         skinframe_t *skinframe;
3319         rtexture_t *ddsbase = NULL;
3320         qboolean ddshasalpha = false;
3321         float ddsavgcolor[4];
3322         char basename[MAX_QPATH];
3323         int miplevel = R_PicmipForFlags(textureflags);
3324         int savemiplevel = miplevel;
3325         int mymiplevel;
3326         char vabuf[1024];
3327
3328         if (cls.state == ca_dedicated)
3329                 return NULL;
3330
3331         // return an existing skinframe if already loaded
3332         // if loading of the first image fails, don't make a new skinframe as it
3333         // would cause all future lookups of this to be missing
3334         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3335         if (skinframe && skinframe->base)
3336                 return skinframe;
3337
3338         Image_StripImageExtension(name, basename, sizeof(basename));
3339
3340         // check for DDS texture file first
3341         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3342         {
3343                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3344                 if (basepixels == NULL)
3345                         return NULL;
3346         }
3347
3348         // FIXME handle miplevel
3349
3350         if (developer_loading.integer)
3351                 Con_Printf("loading skin \"%s\"\n", name);
3352
3353         // we've got some pixels to store, so really allocate this new texture now
3354         if (!skinframe)
3355                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3356         textureflags &= ~TEXF_FORCE_RELOAD;
3357         skinframe->stain = NULL;
3358         skinframe->merged = NULL;
3359         skinframe->base = NULL;
3360         skinframe->pants = NULL;
3361         skinframe->shirt = NULL;
3362         skinframe->nmap = NULL;
3363         skinframe->gloss = NULL;
3364         skinframe->glow = NULL;
3365         skinframe->fog = NULL;
3366         skinframe->reflect = NULL;
3367         skinframe->hasalpha = false;
3368
3369         if (ddsbase)
3370         {
3371                 skinframe->base = ddsbase;
3372                 skinframe->hasalpha = ddshasalpha;
3373                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3374                 if (r_loadfog && skinframe->hasalpha)
3375                         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);
3376                 //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]);
3377         }
3378         else
3379         {
3380                 basepixels_width = image_width;
3381                 basepixels_height = image_height;
3382                 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);
3383                 if (textureflags & TEXF_ALPHA)
3384                 {
3385                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3386                         {
3387                                 if (basepixels[j] < 255)
3388                                 {
3389                                         skinframe->hasalpha = true;
3390                                         break;
3391                                 }
3392                         }
3393                         if (r_loadfog && skinframe->hasalpha)
3394                         {
3395                                 // has transparent pixels
3396                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3397                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3398                                 {
3399                                         pixels[j+0] = 255;
3400                                         pixels[j+1] = 255;
3401                                         pixels[j+2] = 255;
3402                                         pixels[j+3] = basepixels[j+3];
3403                                 }
3404                                 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);
3405                                 Mem_Free(pixels);
3406                         }
3407                 }
3408                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3409 #ifndef USE_GLES2
3410                 //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]);
3411                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3412                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3413                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3414                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3415 #endif
3416         }
3417
3418         if (r_loaddds)
3419         {
3420                 mymiplevel = savemiplevel;
3421                 if (r_loadnormalmap)
3422                         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);
3423                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3424                 if (r_loadgloss)
3425                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3426                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3427                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3428                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3429         }
3430
3431         // _norm is the name used by tenebrae and has been adopted as standard
3432         if (r_loadnormalmap && skinframe->nmap == NULL)
3433         {
3434                 mymiplevel = savemiplevel;
3435                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3436                 {
3437                         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);
3438                         Mem_Free(pixels);
3439                         pixels = NULL;
3440                 }
3441                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3442                 {
3443                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3444                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3445                         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);
3446                         Mem_Free(pixels);
3447                         Mem_Free(bumppixels);
3448                 }
3449                 else if (r_shadow_bumpscale_basetexture.value > 0)
3450                 {
3451                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3452                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3453                         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);
3454                         Mem_Free(pixels);
3455                 }
3456 #ifndef USE_GLES2
3457                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3458                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3459 #endif
3460         }
3461
3462         // _luma is supported only for tenebrae compatibility
3463         // _glow is the preferred name
3464         mymiplevel = savemiplevel;
3465         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))))
3466         {
3467                 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);
3468 #ifndef USE_GLES2
3469                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3470                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3471 #endif
3472                 Mem_Free(pixels);pixels = NULL;
3473         }
3474
3475         mymiplevel = savemiplevel;
3476         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3477         {
3478                 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);
3479 #ifndef USE_GLES2
3480                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3481                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3482 #endif
3483                 Mem_Free(pixels);
3484                 pixels = NULL;
3485         }
3486
3487         mymiplevel = savemiplevel;
3488         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3489         {
3490                 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);
3491 #ifndef USE_GLES2
3492                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3493                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3494 #endif
3495                 Mem_Free(pixels);
3496                 pixels = NULL;
3497         }
3498
3499         mymiplevel = savemiplevel;
3500         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3501         {
3502                 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);
3503 #ifndef USE_GLES2
3504                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3505                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3506 #endif
3507                 Mem_Free(pixels);
3508                 pixels = NULL;
3509         }
3510
3511         mymiplevel = savemiplevel;
3512         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3513         {
3514                 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);
3515 #ifndef USE_GLES2
3516                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3517                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3518 #endif
3519                 Mem_Free(pixels);
3520                 pixels = NULL;
3521         }
3522
3523         if (basepixels)
3524                 Mem_Free(basepixels);
3525
3526         return skinframe;
3527 }
3528
3529 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3530 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3531 {
3532         int i;
3533         unsigned char *temp1, *temp2;
3534         skinframe_t *skinframe;
3535         char vabuf[1024];
3536
3537         if (cls.state == ca_dedicated)
3538                 return NULL;
3539
3540         // if already loaded just return it, otherwise make a new skinframe
3541         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3542         if (skinframe->base)
3543                 return skinframe;
3544         textureflags &= ~TEXF_FORCE_RELOAD;
3545
3546         skinframe->stain = NULL;
3547         skinframe->merged = NULL;
3548         skinframe->base = NULL;
3549         skinframe->pants = NULL;
3550         skinframe->shirt = NULL;
3551         skinframe->nmap = NULL;
3552         skinframe->gloss = NULL;
3553         skinframe->glow = NULL;
3554         skinframe->fog = NULL;
3555         skinframe->reflect = NULL;
3556         skinframe->hasalpha = false;
3557
3558         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3559         if (!skindata)
3560                 return NULL;
3561
3562         if (developer_loading.integer)
3563                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3564
3565         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3566         {
3567                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3568                 temp2 = temp1 + width * height * 4;
3569                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3570                 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);
3571                 Mem_Free(temp1);
3572         }
3573         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3574         if (textureflags & TEXF_ALPHA)
3575         {
3576                 for (i = 3;i < width * height * 4;i += 4)
3577                 {
3578                         if (skindata[i] < 255)
3579                         {
3580                                 skinframe->hasalpha = true;
3581                                 break;
3582                         }
3583                 }
3584                 if (r_loadfog && skinframe->hasalpha)
3585                 {
3586                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3587                         memcpy(fogpixels, skindata, width * height * 4);
3588                         for (i = 0;i < width * height * 4;i += 4)
3589                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3590                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3591                         Mem_Free(fogpixels);
3592                 }
3593         }
3594
3595         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3596         //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]);
3597
3598         return skinframe;
3599 }
3600
3601 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3602 {
3603         int i;
3604         int featuresmask;
3605         skinframe_t *skinframe;
3606
3607         if (cls.state == ca_dedicated)
3608                 return NULL;
3609
3610         // if already loaded just return it, otherwise make a new skinframe
3611         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3612         if (skinframe->base)
3613                 return skinframe;
3614         //textureflags &= ~TEXF_FORCE_RELOAD;
3615
3616         skinframe->stain = NULL;
3617         skinframe->merged = NULL;
3618         skinframe->base = NULL;
3619         skinframe->pants = NULL;
3620         skinframe->shirt = NULL;
3621         skinframe->nmap = NULL;
3622         skinframe->gloss = NULL;
3623         skinframe->glow = NULL;
3624         skinframe->fog = NULL;
3625         skinframe->reflect = NULL;
3626         skinframe->hasalpha = false;
3627
3628         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3629         if (!skindata)
3630                 return NULL;
3631
3632         if (developer_loading.integer)
3633                 Con_Printf("loading quake skin \"%s\"\n", name);
3634
3635         // 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)
3636         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3637         memcpy(skinframe->qpixels, skindata, width*height);
3638         skinframe->qwidth = width;
3639         skinframe->qheight = height;
3640
3641         featuresmask = 0;
3642         for (i = 0;i < width * height;i++)
3643                 featuresmask |= palette_featureflags[skindata[i]];
3644
3645         skinframe->hasalpha = false;
3646         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3647         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3648         skinframe->qgeneratemerged = true;
3649         skinframe->qgeneratebase = skinframe->qhascolormapping;
3650         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3651
3652         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3653         //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]);
3654
3655         return skinframe;
3656 }
3657
3658 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3659 {
3660         int width;
3661         int height;
3662         unsigned char *skindata;
3663         char vabuf[1024];
3664
3665         if (!skinframe->qpixels)
3666                 return;
3667
3668         if (!skinframe->qhascolormapping)
3669                 colormapped = false;
3670
3671         if (colormapped)
3672         {
3673                 if (!skinframe->qgeneratebase)
3674                         return;
3675         }
3676         else
3677         {
3678                 if (!skinframe->qgeneratemerged)
3679                         return;
3680         }
3681
3682         width = skinframe->qwidth;
3683         height = skinframe->qheight;
3684         skindata = skinframe->qpixels;
3685
3686         if (skinframe->qgeneratenmap)
3687         {
3688                 unsigned char *temp1, *temp2;
3689                 skinframe->qgeneratenmap = false;
3690                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3691                 temp2 = temp1 + width * height * 4;
3692                 // use either a custom palette or the quake palette
3693                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3694                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3695                 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);
3696                 Mem_Free(temp1);
3697         }
3698
3699         if (skinframe->qgenerateglow)
3700         {
3701                 skinframe->qgenerateglow = false;
3702                 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
3703         }
3704
3705         if (colormapped)
3706         {
3707                 skinframe->qgeneratebase = false;
3708                 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);
3709                 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);
3710                 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);
3711         }
3712         else
3713         {
3714                 skinframe->qgeneratemerged = false;
3715                 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);
3716         }
3717
3718         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3719         {
3720                 Mem_Free(skinframe->qpixels);
3721                 skinframe->qpixels = NULL;
3722         }
3723 }
3724
3725 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)
3726 {
3727         int i;
3728         skinframe_t *skinframe;
3729         char vabuf[1024];
3730
3731         if (cls.state == ca_dedicated)
3732                 return NULL;
3733
3734         // if already loaded just return it, otherwise make a new skinframe
3735         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3736         if (skinframe->base)
3737                 return skinframe;
3738         textureflags &= ~TEXF_FORCE_RELOAD;
3739
3740         skinframe->stain = NULL;
3741         skinframe->merged = NULL;
3742         skinframe->base = NULL;
3743         skinframe->pants = NULL;
3744         skinframe->shirt = NULL;
3745         skinframe->nmap = NULL;
3746         skinframe->gloss = NULL;
3747         skinframe->glow = NULL;
3748         skinframe->fog = NULL;
3749         skinframe->reflect = NULL;
3750         skinframe->hasalpha = false;
3751
3752         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3753         if (!skindata)
3754                 return NULL;
3755
3756         if (developer_loading.integer)
3757                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3758
3759         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3760         if (textureflags & TEXF_ALPHA)
3761         {
3762                 for (i = 0;i < width * height;i++)
3763                 {
3764                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3765                         {
3766                                 skinframe->hasalpha = true;
3767                                 break;
3768                         }
3769                 }
3770                 if (r_loadfog && skinframe->hasalpha)
3771                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3772         }
3773
3774         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3775         //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]);
3776
3777         return skinframe;
3778 }
3779
3780 skinframe_t *R_SkinFrame_LoadMissing(void)
3781 {
3782         skinframe_t *skinframe;
3783
3784         if (cls.state == ca_dedicated)
3785                 return NULL;
3786
3787         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3788         skinframe->stain = NULL;
3789         skinframe->merged = NULL;
3790         skinframe->base = NULL;
3791         skinframe->pants = NULL;
3792         skinframe->shirt = NULL;
3793         skinframe->nmap = NULL;
3794         skinframe->gloss = NULL;
3795         skinframe->glow = NULL;
3796         skinframe->fog = NULL;
3797         skinframe->reflect = NULL;
3798         skinframe->hasalpha = false;
3799
3800         skinframe->avgcolor[0] = rand() / RAND_MAX;
3801         skinframe->avgcolor[1] = rand() / RAND_MAX;
3802         skinframe->avgcolor[2] = rand() / RAND_MAX;
3803         skinframe->avgcolor[3] = 1;
3804
3805         return skinframe;
3806 }
3807
3808 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3809 typedef struct suffixinfo_s
3810 {
3811         const char *suffix;
3812         qboolean flipx, flipy, flipdiagonal;
3813 }
3814 suffixinfo_t;
3815 static suffixinfo_t suffix[3][6] =
3816 {
3817         {
3818                 {"px",   false, false, false},
3819                 {"nx",   false, false, false},
3820                 {"py",   false, false, false},
3821                 {"ny",   false, false, false},
3822                 {"pz",   false, false, false},
3823                 {"nz",   false, false, false}
3824         },
3825         {
3826                 {"posx", false, false, false},
3827                 {"negx", false, false, false},
3828                 {"posy", false, false, false},
3829                 {"negy", false, false, false},
3830                 {"posz", false, false, false},
3831                 {"negz", false, false, false}
3832         },
3833         {
3834                 {"rt",    true, false,  true},
3835                 {"lf",   false,  true,  true},
3836                 {"ft",    true,  true, false},
3837                 {"bk",   false, false, false},
3838                 {"up",    true, false,  true},
3839                 {"dn",    true, false,  true}
3840         }
3841 };
3842
3843 static int componentorder[4] = {0, 1, 2, 3};
3844
3845 static rtexture_t *R_LoadCubemap(const char *basename)
3846 {
3847         int i, j, cubemapsize;
3848         unsigned char *cubemappixels, *image_buffer;
3849         rtexture_t *cubemaptexture;
3850         char name[256];
3851         // must start 0 so the first loadimagepixels has no requested width/height
3852         cubemapsize = 0;
3853         cubemappixels = NULL;
3854         cubemaptexture = NULL;
3855         // keep trying different suffix groups (posx, px, rt) until one loads
3856         for (j = 0;j < 3 && !cubemappixels;j++)
3857         {
3858                 // load the 6 images in the suffix group
3859                 for (i = 0;i < 6;i++)
3860                 {
3861                         // generate an image name based on the base and and suffix
3862                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3863                         // load it
3864                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3865                         {
3866                                 // an image loaded, make sure width and height are equal
3867                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3868                                 {
3869                                         // if this is the first image to load successfully, allocate the cubemap memory
3870                                         if (!cubemappixels && image_width >= 1)
3871                                         {
3872                                                 cubemapsize = image_width;
3873                                                 // note this clears to black, so unavailable sides are black
3874                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3875                                         }
3876                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3877                                         if (cubemappixels)
3878                                                 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);
3879                                 }
3880                                 else
3881                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3882                                 // free the image
3883                                 Mem_Free(image_buffer);
3884                         }
3885                 }
3886         }
3887         // if a cubemap loaded, upload it
3888         if (cubemappixels)
3889         {
3890                 if (developer_loading.integer)
3891                         Con_Printf("loading cubemap \"%s\"\n", basename);
3892
3893                 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);
3894                 Mem_Free(cubemappixels);
3895         }
3896         else
3897         {
3898                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3899                 if (developer_loading.integer)
3900                 {
3901                         Con_Printf("(tried tried images ");
3902                         for (j = 0;j < 3;j++)
3903                                 for (i = 0;i < 6;i++)
3904                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3905                         Con_Print(" and was unable to find any of them).\n");
3906                 }
3907         }
3908         return cubemaptexture;
3909 }
3910
3911 rtexture_t *R_GetCubemap(const char *basename)
3912 {
3913         int i;
3914         for (i = 0;i < r_texture_numcubemaps;i++)
3915                 if (r_texture_cubemaps[i] != NULL)
3916                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3917                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3918         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3919                 return r_texture_whitecube;
3920         r_texture_numcubemaps++;
3921         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3922         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3923         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3924         return r_texture_cubemaps[i]->texture;
3925 }
3926
3927 static void R_Main_FreeViewCache(void)
3928 {
3929         if (r_refdef.viewcache.entityvisible)
3930                 Mem_Free(r_refdef.viewcache.entityvisible);
3931         if (r_refdef.viewcache.world_pvsbits)
3932                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3933         if (r_refdef.viewcache.world_leafvisible)
3934                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3935         if (r_refdef.viewcache.world_surfacevisible)
3936                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3937         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3938 }
3939
3940 static void R_Main_ResizeViewCache(void)
3941 {
3942         int numentities = r_refdef.scene.numentities;
3943         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3944         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3945         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3946         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3947         if (r_refdef.viewcache.maxentities < numentities)
3948         {
3949                 r_refdef.viewcache.maxentities = numentities;
3950                 if (r_refdef.viewcache.entityvisible)
3951                         Mem_Free(r_refdef.viewcache.entityvisible);
3952                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3953         }
3954         if (r_refdef.viewcache.world_numclusters != numclusters)
3955         {
3956                 r_refdef.viewcache.world_numclusters = numclusters;
3957                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3958                 if (r_refdef.viewcache.world_pvsbits)
3959                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3960                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3961         }
3962         if (r_refdef.viewcache.world_numleafs != numleafs)
3963         {
3964                 r_refdef.viewcache.world_numleafs = numleafs;
3965                 if (r_refdef.viewcache.world_leafvisible)
3966                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3967                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3968         }
3969         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3970         {
3971                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3972                 if (r_refdef.viewcache.world_surfacevisible)
3973                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3974                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3975         }
3976 }
3977
3978 extern rtexture_t *loadingscreentexture;
3979 static void gl_main_start(void)
3980 {
3981         loadingscreentexture = NULL;
3982         r_texture_blanknormalmap = NULL;
3983         r_texture_white = NULL;
3984         r_texture_grey128 = NULL;
3985         r_texture_black = NULL;
3986         r_texture_whitecube = NULL;
3987         r_texture_normalizationcube = NULL;
3988         r_texture_fogattenuation = NULL;
3989         r_texture_fogheighttexture = NULL;
3990         r_texture_gammaramps = NULL;
3991         r_texture_numcubemaps = 0;
3992         r_uniformbufferalignment = 32;
3993
3994         r_loaddds = r_texture_dds_load.integer != 0;
3995         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3996
3997         switch(vid.renderpath)
3998         {
3999         case RENDERPATH_GL20:
4000         case RENDERPATH_D3D9:
4001         case RENDERPATH_D3D10:
4002         case RENDERPATH_D3D11:
4003         case RENDERPATH_SOFT:
4004         case RENDERPATH_GLES2:
4005                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4006                 Cvar_SetValueQuick(&gl_combine, 1);
4007                 Cvar_SetValueQuick(&r_glsl, 1);
4008                 r_loadnormalmap = true;
4009                 r_loadgloss = true;
4010                 r_loadfog = false;
4011                 if (vid.support.arb_uniform_buffer_object)
4012                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4013                 break;
4014         case RENDERPATH_GL13:
4015         case RENDERPATH_GLES1:
4016                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4017                 Cvar_SetValueQuick(&gl_combine, 1);
4018                 Cvar_SetValueQuick(&r_glsl, 0);
4019                 r_loadnormalmap = false;
4020                 r_loadgloss = false;
4021                 r_loadfog = true;
4022                 break;
4023         case RENDERPATH_GL11:
4024                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4025                 Cvar_SetValueQuick(&gl_combine, 0);
4026                 Cvar_SetValueQuick(&r_glsl, 0);
4027                 r_loadnormalmap = false;
4028                 r_loadgloss = false;
4029                 r_loadfog = true;
4030                 break;
4031         }
4032
4033         R_AnimCache_Free();
4034         R_FrameData_Reset();
4035         R_BufferData_Reset();
4036
4037         r_numqueries = 0;
4038         r_maxqueries = 0;
4039         memset(r_queries, 0, sizeof(r_queries));
4040
4041         r_qwskincache = NULL;
4042         r_qwskincache_size = 0;
4043
4044         // due to caching of texture_t references, the collision cache must be reset
4045         Collision_Cache_Reset(true);
4046
4047         // set up r_skinframe loading system for textures
4048         memset(&r_skinframe, 0, sizeof(r_skinframe));
4049         r_skinframe.loadsequence = 1;
4050         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4051
4052         r_main_texturepool = R_AllocTexturePool();
4053         R_BuildBlankTextures();
4054         R_BuildNoTexture();
4055         if (vid.support.arb_texture_cube_map)
4056         {
4057                 R_BuildWhiteCube();
4058                 R_BuildNormalizationCube();
4059         }
4060         r_texture_fogattenuation = NULL;
4061         r_texture_fogheighttexture = NULL;
4062         r_texture_gammaramps = NULL;
4063         //r_texture_fogintensity = NULL;
4064         memset(&r_fb, 0, sizeof(r_fb));
4065         r_glsl_permutation = NULL;
4066         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4067         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4068         glslshaderstring = NULL;
4069 #ifdef SUPPORTD3D
4070         r_hlsl_permutation = NULL;
4071         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4072         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4073 #endif
4074         hlslshaderstring = NULL;
4075         memset(&r_svbsp, 0, sizeof (r_svbsp));
4076
4077         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4078         r_texture_numcubemaps = 0;
4079
4080         r_refdef.fogmasktable_density = 0;
4081 }
4082
4083 static void gl_main_shutdown(void)
4084 {
4085         R_AnimCache_Free();
4086         R_FrameData_Reset();
4087         R_BufferData_Reset();
4088
4089         R_Main_FreeViewCache();
4090
4091         switch(vid.renderpath)
4092         {
4093         case RENDERPATH_GL11:
4094         case RENDERPATH_GL13:
4095         case RENDERPATH_GL20:
4096         case RENDERPATH_GLES1:
4097         case RENDERPATH_GLES2:
4098 #ifdef GL_SAMPLES_PASSED_ARB
4099                 if (r_maxqueries)
4100                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4101 #endif
4102                 break;
4103         case RENDERPATH_D3D9:
4104                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4105                 break;
4106         case RENDERPATH_D3D10:
4107                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4108                 break;
4109         case RENDERPATH_D3D11:
4110                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4111                 break;
4112         case RENDERPATH_SOFT:
4113                 break;
4114         }
4115
4116         r_numqueries = 0;
4117         r_maxqueries = 0;
4118         memset(r_queries, 0, sizeof(r_queries));
4119
4120         r_qwskincache = NULL;
4121         r_qwskincache_size = 0;
4122
4123         // clear out the r_skinframe state
4124         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4125         memset(&r_skinframe, 0, sizeof(r_skinframe));
4126
4127         if (r_svbsp.nodes)
4128                 Mem_Free(r_svbsp.nodes);
4129         memset(&r_svbsp, 0, sizeof (r_svbsp));
4130         R_FreeTexturePool(&r_main_texturepool);
4131         loadingscreentexture = NULL;
4132         r_texture_blanknormalmap = NULL;
4133         r_texture_white = NULL;
4134         r_texture_grey128 = NULL;
4135         r_texture_black = NULL;
4136         r_texture_whitecube = NULL;
4137         r_texture_normalizationcube = NULL;
4138         r_texture_fogattenuation = NULL;
4139         r_texture_fogheighttexture = NULL;
4140         r_texture_gammaramps = NULL;
4141         r_texture_numcubemaps = 0;
4142         //r_texture_fogintensity = NULL;
4143         memset(&r_fb, 0, sizeof(r_fb));
4144         R_GLSL_Restart_f();
4145
4146         r_glsl_permutation = NULL;
4147         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4148         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4149         glslshaderstring = NULL;
4150 #ifdef SUPPORTD3D
4151         r_hlsl_permutation = NULL;
4152         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4153         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4154 #endif
4155         hlslshaderstring = NULL;
4156 }
4157
4158 static void gl_main_newmap(void)
4159 {
4160         // FIXME: move this code to client
4161         char *entities, entname[MAX_QPATH];
4162         if (r_qwskincache)
4163                 Mem_Free(r_qwskincache);
4164         r_qwskincache = NULL;
4165         r_qwskincache_size = 0;
4166         if (cl.worldmodel)
4167         {
4168                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4169                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4170                 {
4171                         CL_ParseEntityLump(entities);
4172                         Mem_Free(entities);
4173                         return;
4174                 }
4175                 if (cl.worldmodel->brush.entities)
4176                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4177         }
4178         R_Main_FreeViewCache();
4179
4180         R_FrameData_Reset();
4181         R_BufferData_Reset();
4182 }
4183
4184 void GL_Main_Init(void)
4185 {
4186         int i;
4187         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4188
4189         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4190         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4191         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4192         if (gamemode == GAME_NEHAHRA)
4193         {
4194                 Cvar_RegisterVariable (&gl_fogenable);
4195                 Cvar_RegisterVariable (&gl_fogdensity);
4196                 Cvar_RegisterVariable (&gl_fogred);
4197                 Cvar_RegisterVariable (&gl_foggreen);
4198                 Cvar_RegisterVariable (&gl_fogblue);
4199                 Cvar_RegisterVariable (&gl_fogstart);
4200                 Cvar_RegisterVariable (&gl_fogend);
4201                 Cvar_RegisterVariable (&gl_skyclip);
4202         }
4203         Cvar_RegisterVariable(&r_motionblur);
4204         Cvar_RegisterVariable(&r_damageblur);
4205         Cvar_RegisterVariable(&r_motionblur_averaging);
4206         Cvar_RegisterVariable(&r_motionblur_randomize);
4207         Cvar_RegisterVariable(&r_motionblur_minblur);
4208         Cvar_RegisterVariable(&r_motionblur_maxblur);
4209         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4210         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4211         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4212         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4213         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4214         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4215         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4216         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4217         Cvar_RegisterVariable(&r_equalize_entities_by);
4218         Cvar_RegisterVariable(&r_equalize_entities_to);
4219         Cvar_RegisterVariable(&r_depthfirst);
4220         Cvar_RegisterVariable(&r_useinfinitefarclip);
4221         Cvar_RegisterVariable(&r_farclip_base);
4222         Cvar_RegisterVariable(&r_farclip_world);
4223         Cvar_RegisterVariable(&r_nearclip);
4224         Cvar_RegisterVariable(&r_deformvertexes);
4225         Cvar_RegisterVariable(&r_transparent);
4226         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4227         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4228         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4229         Cvar_RegisterVariable(&r_showoverdraw);
4230         Cvar_RegisterVariable(&r_showbboxes);
4231         Cvar_RegisterVariable(&r_showsurfaces);
4232         Cvar_RegisterVariable(&r_showtris);
4233         Cvar_RegisterVariable(&r_shownormals);
4234         Cvar_RegisterVariable(&r_showlighting);
4235         Cvar_RegisterVariable(&r_showshadowvolumes);
4236         Cvar_RegisterVariable(&r_showcollisionbrushes);
4237         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4238         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4239         Cvar_RegisterVariable(&r_showdisabledepthtest);
4240         Cvar_RegisterVariable(&r_drawportals);
4241         Cvar_RegisterVariable(&r_drawentities);
4242         Cvar_RegisterVariable(&r_draw2d);
4243         Cvar_RegisterVariable(&r_drawworld);
4244         Cvar_RegisterVariable(&r_cullentities_trace);
4245         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4246         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4247         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4248         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4249         Cvar_RegisterVariable(&r_sortentities);
4250         Cvar_RegisterVariable(&r_drawviewmodel);
4251         Cvar_RegisterVariable(&r_drawexteriormodel);
4252         Cvar_RegisterVariable(&r_speeds);
4253         Cvar_RegisterVariable(&r_fullbrights);
4254         Cvar_RegisterVariable(&r_wateralpha);
4255         Cvar_RegisterVariable(&r_dynamic);
4256         Cvar_RegisterVariable(&r_fakelight);
4257         Cvar_RegisterVariable(&r_fakelight_intensity);
4258         Cvar_RegisterVariable(&r_fullbright);
4259         Cvar_RegisterVariable(&r_shadows);
4260         Cvar_RegisterVariable(&r_shadows_darken);
4261         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4262         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4263         Cvar_RegisterVariable(&r_shadows_throwdistance);
4264         Cvar_RegisterVariable(&r_shadows_throwdirection);
4265         Cvar_RegisterVariable(&r_shadows_focus);
4266         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4267         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4268         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4269         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4270         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4271         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4272         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4273         Cvar_RegisterVariable(&r_fog_exp2);
4274         Cvar_RegisterVariable(&r_fog_clear);
4275         Cvar_RegisterVariable(&r_drawfog);
4276         Cvar_RegisterVariable(&r_transparentdepthmasking);
4277         Cvar_RegisterVariable(&r_transparent_sortmindist);
4278         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4279         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4280         Cvar_RegisterVariable(&r_texture_dds_load);
4281         Cvar_RegisterVariable(&r_texture_dds_save);
4282         Cvar_RegisterVariable(&r_textureunits);
4283         Cvar_RegisterVariable(&gl_combine);
4284         Cvar_RegisterVariable(&r_usedepthtextures);
4285         Cvar_RegisterVariable(&r_viewfbo);
4286         Cvar_RegisterVariable(&r_viewscale);
4287         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4288         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4289         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4290         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4291         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4292         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4293         Cvar_RegisterVariable(&r_glsl);
4294         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4295         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4296         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4297         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4298         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4299         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4300         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4301         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4302         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4303         Cvar_RegisterVariable(&r_glsl_postprocess);
4304         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4305         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4306         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4307         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4308         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4309         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4310         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4311         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4312         Cvar_RegisterVariable(&r_celshading);
4313         Cvar_RegisterVariable(&r_celoutlines);
4314
4315         Cvar_RegisterVariable(&r_water);
4316         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4317         Cvar_RegisterVariable(&r_water_clippingplanebias);
4318         Cvar_RegisterVariable(&r_water_refractdistort);
4319         Cvar_RegisterVariable(&r_water_reflectdistort);
4320         Cvar_RegisterVariable(&r_water_scissormode);
4321         Cvar_RegisterVariable(&r_water_lowquality);
4322         Cvar_RegisterVariable(&r_water_hideplayer);
4323         Cvar_RegisterVariable(&r_water_fbo);
4324
4325         Cvar_RegisterVariable(&r_lerpsprites);
4326         Cvar_RegisterVariable(&r_lerpmodels);
4327         Cvar_RegisterVariable(&r_lerplightstyles);
4328         Cvar_RegisterVariable(&r_waterscroll);
4329         Cvar_RegisterVariable(&r_bloom);
4330         Cvar_RegisterVariable(&r_bloom_colorscale);
4331         Cvar_RegisterVariable(&r_bloom_brighten);
4332         Cvar_RegisterVariable(&r_bloom_blur);
4333         Cvar_RegisterVariable(&r_bloom_resolution);
4334         Cvar_RegisterVariable(&r_bloom_colorexponent);
4335         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4336         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4337         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4338         Cvar_RegisterVariable(&r_hdr_glowintensity);
4339         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4340         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4341         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4342         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4343         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4344         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4345         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4346         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4347         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4348         Cvar_RegisterVariable(&developer_texturelogging);
4349         Cvar_RegisterVariable(&gl_lightmaps);
4350         Cvar_RegisterVariable(&r_test);
4351         Cvar_RegisterVariable(&r_batch_multidraw);
4352         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4353         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4354         Cvar_RegisterVariable(&r_glsl_skeletal);
4355         Cvar_RegisterVariable(&r_glsl_saturation);
4356         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4357         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4358         Cvar_RegisterVariable(&r_framedatasize);
4359         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4360                 Cvar_RegisterVariable(&r_buffermegs[i]);
4361         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4362         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4363                 Cvar_SetValue("r_fullbrights", 0);
4364         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4365 }
4366
4367 void Render_Init(void)
4368 {
4369         gl_backend_init();
4370         R_Textures_Init();
4371         GL_Main_Init();
4372         Font_Init();
4373         GL_Draw_Init();
4374         R_Shadow_Init();
4375         R_Sky_Init();
4376         GL_Surf_Init();
4377         Sbar_Init();
4378         R_Particles_Init();
4379         R_Explosion_Init();
4380         R_LightningBeams_Init();
4381         Mod_RenderInit();
4382 }
4383
4384 /*
4385 ===============
4386 GL_Init
4387 ===============
4388 */
4389 #ifndef USE_GLES2
4390 extern char *ENGINE_EXTENSIONS;
4391 void GL_Init (void)
4392 {
4393         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4394         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4395         gl_version = (const char *)qglGetString(GL_VERSION);
4396         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4397
4398         if (!gl_extensions)
4399                 gl_extensions = "";
4400         if (!gl_platformextensions)
4401                 gl_platformextensions = "";
4402
4403         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4404         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4405         Con_Printf("GL_VERSION: %s\n", gl_version);
4406         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4407         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4408
4409         VID_CheckExtensions();
4410
4411         // LordHavoc: report supported extensions
4412         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4413
4414         // clear to black (loading plaque will be seen over this)
4415         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4416 }
4417 #endif
4418
4419 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4420 {
4421         int i;
4422         mplane_t *p;
4423         if (r_trippy.integer)
4424                 return false;
4425         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4426         {
4427                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4428                 if (i == 4)
4429                         continue;
4430                 p = r_refdef.view.frustum + i;
4431                 switch(p->signbits)
4432                 {
4433                 default:
4434                 case 0:
4435                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4436                                 return true;
4437                         break;
4438                 case 1:
4439                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4440                                 return true;
4441                         break;
4442                 case 2:
4443                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4444                                 return true;
4445                         break;
4446                 case 3:
4447                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4448                                 return true;
4449                         break;
4450                 case 4:
4451                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4452                                 return true;
4453                         break;
4454                 case 5:
4455                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4456                                 return true;
4457                         break;
4458                 case 6:
4459                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4460                                 return true;
4461                         break;
4462                 case 7:
4463                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4464                                 return true;
4465                         break;
4466                 }
4467         }
4468         return false;
4469 }
4470
4471 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4472 {
4473         int i;
4474         const mplane_t *p;
4475         if (r_trippy.integer)
4476                 return false;
4477         for (i = 0;i < numplanes;i++)
4478         {
4479                 p = planes + i;
4480                 switch(p->signbits)
4481                 {
4482                 default:
4483                 case 0:
4484                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4485                                 return true;
4486                         break;
4487                 case 1:
4488                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4489                                 return true;
4490                         break;
4491                 case 2:
4492                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4493                                 return true;
4494                         break;
4495                 case 3:
4496                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4497                                 return true;
4498                         break;
4499                 case 4:
4500                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4501                                 return true;
4502                         break;
4503                 case 5:
4504                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4505                                 return true;
4506                         break;
4507                 case 6:
4508                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4509                                 return true;
4510                         break;
4511                 case 7:
4512                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4513                                 return true;
4514                         break;
4515                 }
4516         }
4517         return false;
4518 }
4519
4520 //==================================================================================
4521
4522 // LordHavoc: this stores temporary data used within the same frame
4523
4524 typedef struct r_framedata_mem_s
4525 {
4526         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4527         size_t size; // how much usable space
4528         size_t current; // how much space in use
4529         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4530         size_t wantedsize; // how much space was allocated
4531         unsigned char *data; // start of real data (16byte aligned)
4532 }
4533 r_framedata_mem_t;
4534
4535 static r_framedata_mem_t *r_framedata_mem;
4536
4537 void R_FrameData_Reset(void)
4538 {
4539         while (r_framedata_mem)
4540         {
4541                 r_framedata_mem_t *next = r_framedata_mem->purge;
4542                 Mem_Free(r_framedata_mem);
4543                 r_framedata_mem = next;
4544         }
4545 }
4546
4547 static void R_FrameData_Resize(qboolean mustgrow)
4548 {
4549         size_t wantedsize;
4550         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4551         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4552         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4553         {
4554                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4555                 newmem->wantedsize = wantedsize;
4556                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4557                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4558                 newmem->current = 0;
4559                 newmem->mark = 0;
4560                 newmem->purge = r_framedata_mem;
4561                 r_framedata_mem = newmem;
4562         }
4563 }
4564
4565 void R_FrameData_NewFrame(void)
4566 {
4567         R_FrameData_Resize(false);
4568         if (!r_framedata_mem)
4569                 return;
4570         // if we ran out of space on the last frame, free the old memory now
4571         while (r_framedata_mem->purge)
4572         {
4573                 // repeatedly remove the second item in the list, leaving only head
4574                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4575                 Mem_Free(r_framedata_mem->purge);
4576                 r_framedata_mem->purge = next;
4577         }
4578         // reset the current mem pointer
4579         r_framedata_mem->current = 0;
4580         r_framedata_mem->mark = 0;
4581 }
4582
4583 void *R_FrameData_Alloc(size_t size)
4584 {
4585         void *data;
4586         float newvalue;
4587
4588         // align to 16 byte boundary - the data pointer is already aligned, so we
4589         // only need to ensure the size of every allocation is also aligned
4590         size = (size + 15) & ~15;
4591
4592         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4593         {
4594                 // emergency - we ran out of space, allocate more memory
4595                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4596                 // this might not be a growing it, but we'll allocate another buffer every time
4597                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4598                 R_FrameData_Resize(true);
4599         }
4600
4601         data = r_framedata_mem->data + r_framedata_mem->current;
4602         r_framedata_mem->current += size;
4603
4604         // count the usage for stats
4605         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4606         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4607
4608         return (void *)data;
4609 }
4610
4611 void *R_FrameData_Store(size_t size, void *data)
4612 {
4613         void *d = R_FrameData_Alloc(size);
4614         if (d && data)
4615                 memcpy(d, data, size);
4616         return d;
4617 }
4618
4619 void R_FrameData_SetMark(void)
4620 {
4621         if (!r_framedata_mem)
4622                 return;
4623         r_framedata_mem->mark = r_framedata_mem->current;
4624 }
4625
4626 void R_FrameData_ReturnToMark(void)
4627 {
4628         if (!r_framedata_mem)
4629                 return;
4630         r_framedata_mem->current = r_framedata_mem->mark;
4631 }
4632
4633 //==================================================================================
4634
4635 // avoid reusing the same buffer objects on consecutive frames
4636 #define R_BUFFERDATA_CYCLE 3
4637
4638 typedef struct r_bufferdata_buffer_s
4639 {
4640         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4641         size_t size; // how much usable space
4642         size_t current; // how much space in use
4643         r_meshbuffer_t *buffer; // the buffer itself
4644 }
4645 r_bufferdata_buffer_t;
4646
4647 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4648 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4649
4650 /// frees all dynamic buffers
4651 void R_BufferData_Reset(void)
4652 {
4653         int cycle, type;
4654         r_bufferdata_buffer_t **p, *mem;
4655         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4656         {
4657                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4658                 {
4659                         // free all buffers
4660                         p = &r_bufferdata_buffer[cycle][type];
4661                         while (*p)
4662                         {
4663                                 mem = *p;
4664                                 *p = (*p)->purge;
4665                                 if (mem->buffer)
4666                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4667                                 Mem_Free(mem);
4668                         }
4669                 }
4670         }
4671 }
4672
4673 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4674 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4675 {
4676         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4677         size_t size;
4678         float newvalue = r_buffermegs[type].value;
4679
4680         // increase the cvar if we have to (but only if we already have a mem)
4681         if (mustgrow && mem)
4682                 newvalue *= 2.0f;
4683         newvalue = bound(0.25f, newvalue, 256.0f);
4684         while (newvalue * 1024*1024 < minsize)
4685                 newvalue *= 2.0f;
4686
4687         // clamp the cvar to valid range
4688         newvalue = bound(0.25f, newvalue, 256.0f);
4689         if (r_buffermegs[type].value != newvalue)
4690                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4691
4692         // calculate size in bytes
4693         size = (size_t)(newvalue * 1024*1024);
4694         size = bound(131072, size, 256*1024*1024);
4695
4696         // allocate a new buffer if the size is different (purge old one later)
4697         // or if we were told we must grow the buffer
4698         if (!mem || mem->size != size || mustgrow)
4699         {
4700                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4701                 mem->size = size;
4702                 mem->current = 0;
4703                 if (type == R_BUFFERDATA_VERTEX)
4704                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4705                 else if (type == R_BUFFERDATA_INDEX16)
4706                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4707                 else if (type == R_BUFFERDATA_INDEX32)
4708                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4709                 else if (type == R_BUFFERDATA_UNIFORM)
4710                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4711                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4712                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4713         }
4714 }
4715
4716 void R_BufferData_NewFrame(void)
4717 {
4718         int type;
4719         r_bufferdata_buffer_t **p, *mem;
4720         // cycle to the next frame's buffers
4721         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4722         // if we ran out of space on the last time we used these buffers, free the old memory now
4723         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4724         {
4725                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4726                 {
4727                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4728                         // free all but the head buffer, this is how we recycle obsolete
4729                         // buffers after they are no longer in use
4730                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4731                         while (*p)
4732                         {
4733                                 mem = *p;
4734                                 *p = (*p)->purge;
4735                                 if (mem->buffer)
4736                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4737                                 Mem_Free(mem);
4738                         }
4739                         // reset the current offset
4740                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4741                 }
4742         }
4743 }
4744
4745 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4746 {
4747         r_bufferdata_buffer_t *mem;
4748         int offset = 0;
4749         int padsize;
4750
4751         *returnbufferoffset = 0;
4752
4753         // align size to a byte boundary appropriate for the buffer type, this
4754         // makes all allocations have aligned start offsets
4755         if (type == R_BUFFERDATA_UNIFORM)
4756                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4757         else
4758                 padsize = (datasize + 15) & ~15;
4759
4760         // if we ran out of space in this buffer we must allocate a new one
4761         if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4762                 R_BufferData_Resize(type, true, padsize);
4763
4764         // if the resize did not give us enough memory, fail
4765         if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4766                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4767
4768         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4769         offset = mem->current;
4770         mem->current += padsize;
4771
4772         // upload the data to the buffer at the chosen offset
4773         if (offset == 0)
4774                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4775         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4776
4777         // count the usage for stats
4778         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4779         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4780
4781         // return the buffer offset
4782         *returnbufferoffset = offset;
4783
4784         return mem->buffer;
4785 }
4786
4787 //==================================================================================
4788
4789 // LordHavoc: animcache originally written by Echon, rewritten since then
4790
4791 /**
4792  * Animation cache prevents re-generating mesh data for an animated model
4793  * multiple times in one frame for lighting, shadowing, reflections, etc.
4794  */
4795
4796 void R_AnimCache_Free(void)
4797 {
4798 }
4799
4800 void R_AnimCache_ClearCache(void)
4801 {
4802         int i;
4803         entity_render_t *ent;
4804
4805         for (i = 0;i < r_refdef.scene.numentities;i++)
4806         {
4807                 ent = r_refdef.scene.entities[i];
4808                 ent->animcache_vertex3f = NULL;
4809                 ent->animcache_vertex3f_vertexbuffer = NULL;
4810                 ent->animcache_vertex3f_bufferoffset = 0;
4811                 ent->animcache_normal3f = NULL;
4812                 ent->animcache_normal3f_vertexbuffer = NULL;
4813                 ent->animcache_normal3f_bufferoffset = 0;
4814                 ent->animcache_svector3f = NULL;
4815                 ent->animcache_svector3f_vertexbuffer = NULL;
4816                 ent->animcache_svector3f_bufferoffset = 0;
4817                 ent->animcache_tvector3f = NULL;
4818                 ent->animcache_tvector3f_vertexbuffer = NULL;
4819                 ent->animcache_tvector3f_bufferoffset = 0;
4820                 ent->animcache_vertexmesh = NULL;
4821                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4822                 ent->animcache_vertexmesh_bufferoffset = 0;
4823                 ent->animcache_skeletaltransform3x4 = NULL;
4824                 ent->animcache_skeletaltransform3x4buffer = NULL;
4825                 ent->animcache_skeletaltransform3x4offset = 0;
4826                 ent->animcache_skeletaltransform3x4size = 0;
4827         }
4828 }
4829
4830 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4831 {
4832         int i;
4833
4834         // check if we need the meshbuffers
4835         if (!vid.useinterleavedarrays)
4836                 return;
4837
4838         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4839                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4840         // TODO: upload vertexbuffer?
4841         if (ent->animcache_vertexmesh)
4842         {
4843                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4844                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4845                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4846                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4847                 for (i = 0;i < numvertices;i++)
4848                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4849                 if (ent->animcache_svector3f)
4850                         for (i = 0;i < numvertices;i++)
4851                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4852                 if (ent->animcache_tvector3f)
4853                         for (i = 0;i < numvertices;i++)
4854                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4855                 if (ent->animcache_normal3f)
4856                         for (i = 0;i < numvertices;i++)
4857                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4858         }
4859 }
4860
4861 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4862 {
4863         dp_model_t *model = ent->model;
4864         int numvertices;
4865
4866         // see if this ent is worth caching
4867         if (!model || !model->Draw || !model->AnimateVertices)
4868                 return false;
4869         // nothing to cache if it contains no animations and has no skeleton
4870         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4871                 return false;
4872         // see if it is already cached for gpuskeletal
4873         if (ent->animcache_skeletaltransform3x4)
4874                 return false;
4875         // see if it is already cached as a mesh
4876         if (ent->animcache_vertex3f)
4877         {
4878                 // check if we need to add normals or tangents
4879                 if (ent->animcache_normal3f)
4880                         wantnormals = false;
4881                 if (ent->animcache_svector3f)
4882                         wanttangents = false;
4883                 if (!wantnormals && !wanttangents)
4884                         return false;
4885         }
4886
4887         // check which kind of cache we need to generate
4888         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4889         {
4890                 // cache the skeleton so the vertex shader can use it
4891                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4892                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4893                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4894                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4895                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4896                 // note: this can fail if the buffer is at the grow limit
4897                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4898                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4899         }
4900         else if (ent->animcache_vertex3f)
4901         {
4902                 // mesh was already cached but we may need to add normals/tangents
4903                 // (this only happens with multiple views, reflections, cameras, etc)
4904                 if (wantnormals || wanttangents)
4905                 {
4906                         numvertices = model->surfmesh.num_vertices;
4907                         if (wantnormals)
4908                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4909                         if (wanttangents)
4910                         {
4911                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4912                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4913                         }
4914                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4915                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4916                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4917                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4918                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4919                 }
4920         }
4921         else
4922         {
4923                 // generate mesh cache
4924                 numvertices = model->surfmesh.num_vertices;
4925                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4926                 if (wantnormals)
4927                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4928                 if (wanttangents)
4929                 {
4930                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4931                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4932                 }
4933                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4934                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4935                 if (wantnormals || wanttangents)
4936                 {
4937                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4938                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4939                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4940                 }
4941                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4942                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4943                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4944         }
4945         return true;
4946 }
4947
4948 void R_AnimCache_CacheVisibleEntities(void)
4949 {
4950         int i;
4951         qboolean wantnormals = true;
4952         qboolean wanttangents = !r_showsurfaces.integer;
4953
4954         switch(vid.renderpath)
4955         {
4956         case RENDERPATH_GL20:
4957         case RENDERPATH_D3D9:
4958         case RENDERPATH_D3D10:
4959         case RENDERPATH_D3D11:
4960         case RENDERPATH_GLES2:
4961                 break;
4962         case RENDERPATH_GL11:
4963         case RENDERPATH_GL13:
4964         case RENDERPATH_GLES1:
4965                 wanttangents = false;
4966                 break;
4967         case RENDERPATH_SOFT:
4968                 break;
4969         }
4970
4971         if (r_shownormals.integer)
4972                 wanttangents = wantnormals = true;
4973
4974         // TODO: thread this
4975         // NOTE: R_PrepareRTLights() also caches entities
4976
4977         for (i = 0;i < r_refdef.scene.numentities;i++)
4978                 if (r_refdef.viewcache.entityvisible[i])
4979                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4980 }
4981
4982 //==================================================================================
4983
4984 extern cvar_t r_overheadsprites_pushback;
4985
4986 static void R_View_UpdateEntityLighting (void)
4987 {
4988         int i;
4989         entity_render_t *ent;
4990         vec3_t tempdiffusenormal, avg;
4991         vec_t f, fa, fd, fdd;
4992         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4993
4994         for (i = 0;i < r_refdef.scene.numentities;i++)
4995         {
4996                 ent = r_refdef.scene.entities[i];
4997
4998                 // skip unseen models
4999                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5000                         continue;
5001
5002                 // skip bsp models
5003                 if (ent->model && ent->model == cl.worldmodel)
5004                 {
5005                         // TODO: use modellight for r_ambient settings on world?
5006                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5007                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5008                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5009                         continue;
5010                 }
5011                 
5012                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5013                 {
5014                         // aleady updated by CSQC
5015                         // TODO: force modellight on BSP models in this case?
5016                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5017                 }
5018                 else
5019                 {
5020                         // fetch the lighting from the worldmodel data
5021                         VectorClear(ent->modellight_ambient);
5022                         VectorClear(ent->modellight_diffuse);
5023                         VectorClear(tempdiffusenormal);
5024                         if (ent->flags & RENDER_LIGHT)
5025                         {
5026                                 vec3_t org;
5027                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5028
5029                                 // complete lightning for lit sprites
5030                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5031                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5032                                 {
5033                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5034                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5035                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5036                                 }
5037                                 else
5038                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5039
5040                                 if(ent->flags & RENDER_EQUALIZE)
5041                                 {
5042                                         // first fix up ambient lighting...
5043                                         if(r_equalize_entities_minambient.value > 0)
5044                                         {
5045                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5046                                                 if(fd > 0)
5047                                                 {
5048                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5049                                                         if(fa < r_equalize_entities_minambient.value * fd)
5050                                                         {
5051                                                                 // solve:
5052                                                                 //   fa'/fd' = minambient
5053                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5054                                                                 //   ...
5055                                                                 //   fa' = fd' * minambient
5056                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5057                                                                 //   ...
5058                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5059                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5060                                                                 //   ...
5061                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5062                                                                 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
5063                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5064                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5065                                                         }
5066                                                 }
5067                                         }
5068
5069                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5070                                         {
5071                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5072                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5073                                                 f = fa + 0.25 * fd;
5074                                                 if(f > 0)
5075                                                 {
5076                                                         // adjust brightness and saturation to target
5077                                                         avg[0] = avg[1] = avg[2] = fa / f;
5078                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5079                                                         avg[0] = avg[1] = avg[2] = fd / f;
5080                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5081                                                 }
5082                                         }
5083                                 }
5084                         }
5085                         else // highly rare
5086                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5087                 }
5088
5089                 // move the light direction into modelspace coordinates for lighting code
5090                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5091                 if(VectorLength2(ent->modellight_lightdir) == 0)
5092                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5093                 VectorNormalize(ent->modellight_lightdir);
5094         }
5095 }
5096
5097 #define MAX_LINEOFSIGHTTRACES 64
5098
5099 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5100 {
5101         int i;
5102         vec3_t boxmins, boxmaxs;
5103         vec3_t start;
5104         vec3_t end;
5105         dp_model_t *model = r_refdef.scene.worldmodel;
5106
5107         if (!model || !model->brush.TraceLineOfSight)
5108                 return true;
5109
5110         // expand the box a little
5111         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5112         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5113         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5114         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5115         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5116         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5117
5118         // return true if eye is inside enlarged box
5119         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5120                 return true;
5121
5122         // try center
5123         VectorCopy(eye, start);
5124         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5125         if (model->brush.TraceLineOfSight(model, start, end))
5126                 return true;
5127
5128         // try various random positions
5129         for (i = 0;i < numsamples;i++)
5130         {
5131                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5132                 if (model->brush.TraceLineOfSight(model, start, end))
5133                         return true;
5134         }
5135
5136         return false;
5137 }
5138
5139
5140 static void R_View_UpdateEntityVisible (void)
5141 {
5142         int i;
5143         int renderimask;
5144         int samples;
5145         entity_render_t *ent;
5146
5147         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5148                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5149                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5150                 :                                                          RENDER_EXTERIORMODEL;
5151         if (!r_drawviewmodel.integer)
5152                 renderimask |= RENDER_VIEWMODEL;
5153         if (!r_drawexteriormodel.integer)
5154                 renderimask |= RENDER_EXTERIORMODEL;
5155         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5156         {
5157                 // worldmodel can check visibility
5158                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5159                 for (i = 0;i < r_refdef.scene.numentities;i++)
5160                 {
5161                         ent = r_refdef.scene.entities[i];
5162                         if (!(ent->flags & renderimask))
5163                         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)))
5164                         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))
5165                                 r_refdef.viewcache.entityvisible[i] = true;
5166                 }
5167         }
5168         else
5169         {
5170                 // no worldmodel or it can't check visibility
5171                 for (i = 0;i < r_refdef.scene.numentities;i++)
5172                 {
5173                         ent = r_refdef.scene.entities[i];
5174                         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));
5175                 }
5176         }
5177         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5178                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5179         {
5180                 for (i = 0;i < r_refdef.scene.numentities;i++)
5181                 {
5182                         if (!r_refdef.viewcache.entityvisible[i])
5183                                 continue;
5184                         ent = r_refdef.scene.entities[i];
5185                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5186                         {
5187                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5188                                 if (samples < 0)
5189                                         continue; // temp entities do pvs only
5190                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5191                                         ent->last_trace_visibility = realtime;
5192                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5193                                         r_refdef.viewcache.entityvisible[i] = 0;
5194                         }
5195                 }
5196         }
5197 }
5198
5199 /// only used if skyrendermasked, and normally returns false
5200 static int R_DrawBrushModelsSky (void)
5201 {
5202         int i, sky;
5203         entity_render_t *ent;
5204
5205         sky = false;
5206         for (i = 0;i < r_refdef.scene.numentities;i++)
5207         {
5208                 if (!r_refdef.viewcache.entityvisible[i])
5209                         continue;
5210                 ent = r_refdef.scene.entities[i];
5211                 if (!ent->model || !ent->model->DrawSky)
5212                         continue;
5213                 ent->model->DrawSky(ent);
5214                 sky = true;
5215         }
5216         return sky;
5217 }
5218
5219 static void R_DrawNoModel(entity_render_t *ent);
5220 static void R_DrawModels(void)
5221 {
5222         int i;
5223         entity_render_t *ent;
5224
5225         for (i = 0;i < r_refdef.scene.numentities;i++)
5226         {
5227                 if (!r_refdef.viewcache.entityvisible[i])
5228                         continue;
5229                 ent = r_refdef.scene.entities[i];
5230                 r_refdef.stats[r_stat_entities]++;
5231                 /*
5232                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5233                 {
5234                         vec3_t f, l, u, o;
5235                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5236                         Con_Printf("R_DrawModels\n");
5237                         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]);
5238                         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);
5239                         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);
5240                 }
5241                 */
5242                 if (ent->model && ent->model->Draw != NULL)
5243                         ent->model->Draw(ent);
5244                 else
5245                         R_DrawNoModel(ent);
5246         }
5247 }
5248
5249 static void R_DrawModelsDepth(void)
5250 {
5251         int i;
5252         entity_render_t *ent;
5253
5254         for (i = 0;i < r_refdef.scene.numentities;i++)
5255         {
5256                 if (!r_refdef.viewcache.entityvisible[i])
5257                         continue;
5258                 ent = r_refdef.scene.entities[i];
5259                 if (ent->model && ent->model->DrawDepth != NULL)
5260                         ent->model->DrawDepth(ent);
5261         }
5262 }
5263
5264 static void R_DrawModelsDebug(void)
5265 {
5266         int i;
5267         entity_render_t *ent;
5268
5269         for (i = 0;i < r_refdef.scene.numentities;i++)
5270         {
5271                 if (!r_refdef.viewcache.entityvisible[i])
5272                         continue;
5273                 ent = r_refdef.scene.entities[i];
5274                 if (ent->model && ent->model->DrawDebug != NULL)
5275                         ent->model->DrawDebug(ent);
5276         }
5277 }
5278
5279 static void R_DrawModelsAddWaterPlanes(void)
5280 {
5281         int i;
5282         entity_render_t *ent;
5283
5284         for (i = 0;i < r_refdef.scene.numentities;i++)
5285         {
5286                 if (!r_refdef.viewcache.entityvisible[i])
5287                         continue;
5288                 ent = r_refdef.scene.entities[i];
5289                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5290                         ent->model->DrawAddWaterPlanes(ent);
5291         }
5292 }
5293
5294 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}};
5295
5296 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5297 {
5298         if (r_hdr_irisadaptation.integer)
5299         {
5300                 vec3_t p;
5301                 vec3_t ambient;
5302                 vec3_t diffuse;
5303                 vec3_t diffusenormal;
5304                 vec3_t forward;
5305                 vec_t brightness = 0.0f;
5306                 vec_t goal;
5307                 vec_t current;
5308                 vec_t d;
5309                 int c;
5310                 VectorCopy(r_refdef.view.forward, forward);
5311                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5312                 {
5313                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5314                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5315                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5316                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5317                         d = DotProduct(forward, diffusenormal);
5318                         brightness += VectorLength(ambient);
5319                         if (d > 0)
5320                                 brightness += d * VectorLength(diffuse);
5321                 }
5322                 brightness *= 1.0f / c;
5323                 brightness += 0.00001f; // make sure it's never zero
5324                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5325                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5326                 current = r_hdr_irisadaptation_value.value;
5327                 if (current < goal)
5328                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5329                 else if (current > goal)
5330                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5331                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5332                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5333         }
5334         else if (r_hdr_irisadaptation_value.value != 1.0f)
5335                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5336 }
5337
5338 static void R_View_SetFrustum(const int *scissor)
5339 {
5340         int i;
5341         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5342         vec3_t forward, left, up, origin, v;
5343
5344         if(scissor)
5345         {
5346                 // flipped x coordinates (because x points left here)
5347                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5348                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5349
5350                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5351                 switch(vid.renderpath)
5352                 {
5353                         case RENDERPATH_D3D9:
5354                         case RENDERPATH_D3D10:
5355                         case RENDERPATH_D3D11:
5356                                 // non-flipped y coordinates
5357                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5358                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5359                                 break;
5360                         case RENDERPATH_SOFT:
5361                         case RENDERPATH_GL11:
5362                         case RENDERPATH_GL13:
5363                         case RENDERPATH_GL20:
5364                         case RENDERPATH_GLES1:
5365                         case RENDERPATH_GLES2:
5366                                 // non-flipped y coordinates
5367                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5368                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5369                                 break;
5370                 }
5371         }
5372
5373         // we can't trust r_refdef.view.forward and friends in reflected scenes
5374         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5375
5376 #if 0
5377         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5378         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5379         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5380         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5381         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5382         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5383         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5384         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5385         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5386         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5387         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5388         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5389 #endif
5390
5391 #if 0
5392         zNear = r_refdef.nearclip;
5393         nudge = 1.0 - 1.0 / (1<<23);
5394         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5395         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5396         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5397         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5398         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5399         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5400         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5401         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5402 #endif
5403
5404
5405
5406 #if 0
5407         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5408         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5409         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5410         r_refdef.view.frustum[0].dist = m[15] - m[12];
5411
5412         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5413         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5414         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5415         r_refdef.view.frustum[1].dist = m[15] + m[12];
5416
5417         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5418         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5419         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5420         r_refdef.view.frustum[2].dist = m[15] - m[13];
5421
5422         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5423         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5424         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5425         r_refdef.view.frustum[3].dist = m[15] + m[13];
5426
5427         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5428         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5429         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5430         r_refdef.view.frustum[4].dist = m[15] - m[14];
5431
5432         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5433         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5434         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5435         r_refdef.view.frustum[5].dist = m[15] + m[14];
5436 #endif
5437
5438         if (r_refdef.view.useperspective)
5439         {
5440                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5441                 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]);
5442                 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]);
5443                 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]);
5444                 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]);
5445
5446                 // then the normals from the corners relative to origin
5447                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5448                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5449                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5450                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5451
5452                 // in a NORMAL view, forward cross left == up
5453                 // in a REFLECTED view, forward cross left == down
5454                 // so our cross products above need to be adjusted for a left handed coordinate system
5455                 CrossProduct(forward, left, v);
5456                 if(DotProduct(v, up) < 0)
5457                 {
5458                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5459                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5460                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5461                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5462                 }
5463
5464                 // Leaving those out was a mistake, those were in the old code, and they
5465                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5466                 // I couldn't reproduce it after adding those normalizations. --blub
5467                 VectorNormalize(r_refdef.view.frustum[0].normal);
5468                 VectorNormalize(r_refdef.view.frustum[1].normal);
5469                 VectorNormalize(r_refdef.view.frustum[2].normal);
5470                 VectorNormalize(r_refdef.view.frustum[3].normal);
5471
5472                 // make the corners absolute
5473                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5474                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5475                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5476                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5477
5478                 // one more normal
5479                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5480
5481                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5482                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5483                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5484                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5485                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5486         }
5487         else
5488         {
5489                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5490                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5491                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5492                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5493                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5494                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5495                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5496                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5497                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5498                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5499         }
5500         r_refdef.view.numfrustumplanes = 5;
5501
5502         if (r_refdef.view.useclipplane)
5503         {
5504                 r_refdef.view.numfrustumplanes = 6;
5505                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5506         }
5507
5508         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5509                 PlaneClassify(r_refdef.view.frustum + i);
5510
5511         // LordHavoc: note to all quake engine coders, Quake had a special case
5512         // for 90 degrees which assumed a square view (wrong), so I removed it,
5513         // Quake2 has it disabled as well.
5514
5515         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5516         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5517         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5518         //PlaneClassify(&frustum[0]);
5519
5520         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5521         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5522         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5523         //PlaneClassify(&frustum[1]);
5524
5525         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5526         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5527         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5528         //PlaneClassify(&frustum[2]);
5529
5530         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5531         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5532         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5533         //PlaneClassify(&frustum[3]);
5534
5535         // nearclip plane
5536         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5537         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5538         //PlaneClassify(&frustum[4]);
5539 }
5540
5541 static void R_View_UpdateWithScissor(const int *myscissor)
5542 {
5543         R_Main_ResizeViewCache();
5544         R_View_SetFrustum(myscissor);
5545         R_View_WorldVisibility(r_refdef.view.useclipplane);
5546         R_View_UpdateEntityVisible();
5547         R_View_UpdateEntityLighting();
5548 }
5549
5550 static void R_View_Update(void)
5551 {
5552         R_Main_ResizeViewCache();
5553         R_View_SetFrustum(NULL);
5554         R_View_WorldVisibility(r_refdef.view.useclipplane);
5555         R_View_UpdateEntityVisible();
5556         R_View_UpdateEntityLighting();
5557 }
5558
5559 float viewscalefpsadjusted = 1.0f;
5560
5561 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5562 {
5563         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5564         scale = bound(0.03125f, scale, 1.0f);
5565         *outwidth = (int)ceil(width * scale);
5566         *outheight = (int)ceil(height * scale);
5567 }
5568
5569 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5570 {
5571         const float *customclipplane = NULL;
5572         float plane[4];
5573         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5574         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5575         {
5576                 // LordHavoc: couldn't figure out how to make this approach the
5577                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5578                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5579                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5580                         dist = r_refdef.view.clipplane.dist;
5581                 plane[0] = r_refdef.view.clipplane.normal[0];
5582                 plane[1] = r_refdef.view.clipplane.normal[1];
5583                 plane[2] = r_refdef.view.clipplane.normal[2];
5584                 plane[3] = -dist;
5585                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5586         }
5587
5588         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5589         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5590
5591         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5592         if (!r_refdef.view.useperspective)
5593                 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);
5594         else if (vid.stencil && r_useinfinitefarclip.integer)
5595                 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);
5596         else
5597                 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);
5598         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5599         R_SetViewport(&r_refdef.view.viewport);
5600         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5601         {
5602                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5603                 float screenplane[4];
5604                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5605                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5606                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5607                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5608                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5609         }
5610 }
5611
5612 void R_EntityMatrix(const matrix4x4_t *matrix)
5613 {
5614         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5615         {
5616                 gl_modelmatrixchanged = false;
5617                 gl_modelmatrix = *matrix;
5618                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5619                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5620                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5621                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5622                 CHECKGLERROR
5623                 switch(vid.renderpath)
5624                 {
5625                 case RENDERPATH_D3D9:
5626 #ifdef SUPPORTD3D
5627                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5628                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5629 #endif
5630                         break;
5631                 case RENDERPATH_D3D10:
5632                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5633                         break;
5634                 case RENDERPATH_D3D11:
5635                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5636                         break;
5637                 case RENDERPATH_GL11:
5638                 case RENDERPATH_GL13:
5639                 case RENDERPATH_GLES1:
5640                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5641                         break;
5642                 case RENDERPATH_SOFT:
5643                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5644                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5645                         break;
5646                 case RENDERPATH_GL20:
5647                 case RENDERPATH_GLES2:
5648                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5649                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5650                         break;
5651                 }
5652         }
5653 }
5654
5655 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5656 {
5657         r_viewport_t viewport;
5658
5659         CHECKGLERROR
5660
5661         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5662         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);
5663         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5664         R_SetViewport(&viewport);
5665         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5666         GL_Color(1, 1, 1, 1);
5667         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5668         GL_BlendFunc(GL_ONE, GL_ZERO);
5669         GL_ScissorTest(false);
5670         GL_DepthMask(false);
5671         GL_DepthRange(0, 1);
5672         GL_DepthTest(false);
5673         GL_DepthFunc(GL_LEQUAL);
5674         R_EntityMatrix(&identitymatrix);
5675         R_Mesh_ResetTextureState();
5676         GL_PolygonOffset(0, 0);
5677         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5678         switch(vid.renderpath)
5679         {
5680         case RENDERPATH_GL11:
5681         case RENDERPATH_GL13:
5682         case RENDERPATH_GL20:
5683         case RENDERPATH_GLES1:
5684         case RENDERPATH_GLES2:
5685                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5686                 break;
5687         case RENDERPATH_D3D9:
5688         case RENDERPATH_D3D10:
5689         case RENDERPATH_D3D11:
5690         case RENDERPATH_SOFT:
5691                 break;
5692         }
5693         GL_CullFace(GL_NONE);
5694
5695         CHECKGLERROR
5696 }
5697
5698 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5699 {
5700         DrawQ_Finish();
5701
5702         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5703 }
5704
5705 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5706 {
5707         DrawQ_Finish();
5708
5709         R_SetupView(true, fbo, depthtexture, colortexture);
5710         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5711         GL_Color(1, 1, 1, 1);
5712         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5713         GL_BlendFunc(GL_ONE, GL_ZERO);
5714         GL_ScissorTest(true);
5715         GL_DepthMask(true);
5716         GL_DepthRange(0, 1);
5717         GL_DepthTest(true);
5718         GL_DepthFunc(GL_LEQUAL);
5719         R_EntityMatrix(&identitymatrix);
5720         R_Mesh_ResetTextureState();
5721         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5722         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5723         switch(vid.renderpath)
5724         {
5725         case RENDERPATH_GL11:
5726         case RENDERPATH_GL13:
5727         case RENDERPATH_GL20:
5728         case RENDERPATH_GLES1:
5729         case RENDERPATH_GLES2:
5730                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5731                 break;
5732         case RENDERPATH_D3D9:
5733         case RENDERPATH_D3D10:
5734         case RENDERPATH_D3D11:
5735         case RENDERPATH_SOFT:
5736                 break;
5737         }
5738         GL_CullFace(r_refdef.view.cullface_back);
5739 }
5740
5741 /*
5742 ================
5743 R_RenderView_UpdateViewVectors
5744 ================
5745 */
5746 void R_RenderView_UpdateViewVectors(void)
5747 {
5748         // break apart the view matrix into vectors for various purposes
5749         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5750         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5751         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5752         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5753         // make an inverted copy of the view matrix for tracking sprites
5754         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5755 }
5756
5757 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5758 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5759
5760 static void R_Water_StartFrame(void)
5761 {
5762         int i;
5763         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5764         r_waterstate_waterplane_t *p;
5765         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;
5766
5767         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5768                 return;
5769
5770         switch(vid.renderpath)
5771         {
5772         case RENDERPATH_GL20:
5773         case RENDERPATH_D3D9:
5774         case RENDERPATH_D3D10:
5775         case RENDERPATH_D3D11:
5776         case RENDERPATH_SOFT:
5777         case RENDERPATH_GLES2:
5778                 break;
5779         case RENDERPATH_GL11:
5780         case RENDERPATH_GL13:
5781         case RENDERPATH_GLES1:
5782                 return;
5783         }
5784
5785         // set waterwidth and waterheight to the water resolution that will be
5786         // used (often less than the screen resolution for faster rendering)
5787         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5788
5789         // calculate desired texture sizes
5790         // can't use water if the card does not support the texture size
5791         if (!r_water.integer || r_showsurfaces.integer)
5792                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5793         else if (vid.support.arb_texture_non_power_of_two)
5794         {
5795                 texturewidth = waterwidth;
5796                 textureheight = waterheight;
5797                 camerawidth = waterwidth;
5798                 cameraheight = waterheight;
5799         }
5800         else
5801         {
5802                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5803                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5804                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5805                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5806         }
5807
5808         // allocate textures as needed
5809         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))
5810         {
5811                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5812                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5813                 {
5814                         if (p->texture_refraction)
5815                                 R_FreeTexture(p->texture_refraction);
5816                         p->texture_refraction = NULL;
5817                         if (p->fbo_refraction)
5818                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5819                         p->fbo_refraction = 0;
5820                         if (p->texture_reflection)
5821                                 R_FreeTexture(p->texture_reflection);
5822                         p->texture_reflection = NULL;
5823                         if (p->fbo_reflection)
5824                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5825                         p->fbo_reflection = 0;
5826                         if (p->texture_camera)
5827                                 R_FreeTexture(p->texture_camera);
5828                         p->texture_camera = NULL;
5829                         if (p->fbo_camera)
5830                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5831                         p->fbo_camera = 0;
5832                 }
5833                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5834                 r_fb.water.texturewidth = texturewidth;
5835                 r_fb.water.textureheight = textureheight;
5836                 r_fb.water.camerawidth = camerawidth;
5837                 r_fb.water.cameraheight = cameraheight;
5838         }
5839
5840         if (r_fb.water.texturewidth)
5841         {
5842                 int scaledwidth, scaledheight;
5843
5844                 r_fb.water.enabled = true;
5845
5846                 // water resolution is usually reduced
5847                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5848                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5849                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5850
5851                 // set up variables that will be used in shader setup
5852                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5853                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5854                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5855                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5856         }
5857
5858         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5859         r_fb.water.numwaterplanes = 0;
5860 }
5861
5862 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5863 {
5864         int planeindex, bestplaneindex, vertexindex;
5865         vec3_t mins, maxs, normal, center, v, n;
5866         vec_t planescore, bestplanescore;
5867         mplane_t plane;
5868         r_waterstate_waterplane_t *p;
5869         texture_t *t = R_GetCurrentTexture(surface->texture);
5870
5871         rsurface.texture = t;
5872         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5873         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5874         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5875                 return;
5876         // average the vertex normals, find the surface bounds (after deformvertexes)
5877         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5878         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5879         VectorCopy(n, normal);
5880         VectorCopy(v, mins);
5881         VectorCopy(v, maxs);
5882         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5883         {
5884                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5885                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5886                 VectorAdd(normal, n, normal);
5887                 mins[0] = min(mins[0], v[0]);
5888                 mins[1] = min(mins[1], v[1]);
5889                 mins[2] = min(mins[2], v[2]);
5890                 maxs[0] = max(maxs[0], v[0]);
5891                 maxs[1] = max(maxs[1], v[1]);
5892                 maxs[2] = max(maxs[2], v[2]);
5893         }
5894         VectorNormalize(normal);
5895         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5896
5897         VectorCopy(normal, plane.normal);
5898         VectorNormalize(plane.normal);
5899         plane.dist = DotProduct(center, plane.normal);
5900         PlaneClassify(&plane);
5901         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5902         {
5903                 // skip backfaces (except if nocullface is set)
5904 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5905 //                      return;
5906                 VectorNegate(plane.normal, plane.normal);
5907                 plane.dist *= -1;
5908                 PlaneClassify(&plane);
5909         }
5910
5911
5912         // find a matching plane if there is one
5913         bestplaneindex = -1;
5914         bestplanescore = 1048576.0f;
5915         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5916         {
5917                 if(p->camera_entity == t->camera_entity)
5918                 {
5919                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5920                         if (bestplaneindex < 0 || bestplanescore > planescore)
5921                         {
5922                                 bestplaneindex = planeindex;
5923                                 bestplanescore = planescore;
5924                         }
5925                 }
5926         }
5927         planeindex = bestplaneindex;
5928         p = r_fb.water.waterplanes + planeindex;
5929
5930         // if this surface does not fit any known plane rendered this frame, add one
5931         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5932         {
5933                 // store the new plane
5934                 planeindex = r_fb.water.numwaterplanes++;
5935                 p = r_fb.water.waterplanes + planeindex;
5936                 p->plane = plane;
5937                 // clear materialflags and pvs
5938                 p->materialflags = 0;
5939                 p->pvsvalid = false;
5940                 p->camera_entity = t->camera_entity;
5941                 VectorCopy(mins, p->mins);
5942                 VectorCopy(maxs, p->maxs);
5943         }
5944         else
5945         {
5946                 // merge mins/maxs when we're adding this surface to the plane
5947                 p->mins[0] = min(p->mins[0], mins[0]);
5948                 p->mins[1] = min(p->mins[1], mins[1]);
5949                 p->mins[2] = min(p->mins[2], mins[2]);
5950                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5951                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5952                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5953         }
5954         // merge this surface's materialflags into the waterplane
5955         p->materialflags |= t->currentmaterialflags;
5956         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5957         {
5958                 // merge this surface's PVS into the waterplane
5959                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5960                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5961                 {
5962                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5963                         p->pvsvalid = true;
5964                 }
5965         }
5966 }
5967
5968 extern cvar_t r_drawparticles;
5969 extern cvar_t r_drawdecals;
5970
5971 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5972 {
5973         int myscissor[4];
5974         r_refdef_view_t originalview;
5975         r_refdef_view_t myview;
5976         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;
5977         r_waterstate_waterplane_t *p;
5978         vec3_t visorigin;
5979         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;
5980         char vabuf[1024];
5981
5982         originalview = r_refdef.view;
5983
5984         // lowquality hack, temporarily shut down some cvars and restore afterwards
5985         qualityreduction = r_water_lowquality.integer;
5986         if (qualityreduction > 0)
5987         {
5988                 if (qualityreduction >= 1)
5989                 {
5990                         old_r_shadows = r_shadows.integer;
5991                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5992                         old_r_dlight = r_shadow_realtime_dlight.integer;
5993                         Cvar_SetValueQuick(&r_shadows, 0);
5994                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5995                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5996                 }
5997                 if (qualityreduction >= 2)
5998                 {
5999                         old_r_dynamic = r_dynamic.integer;
6000                         old_r_particles = r_drawparticles.integer;
6001                         old_r_decals = r_drawdecals.integer;
6002                         Cvar_SetValueQuick(&r_dynamic, 0);
6003                         Cvar_SetValueQuick(&r_drawparticles, 0);
6004                         Cvar_SetValueQuick(&r_drawdecals, 0);
6005                 }
6006         }
6007
6008         // make sure enough textures are allocated
6009         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6010         {
6011                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6012                 {
6013                         if (!p->texture_refraction)
6014                                 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);
6015                         if (!p->texture_refraction)
6016                                 goto error;
6017                         if (usewaterfbo)
6018                         {
6019                                 if (r_fb.water.depthtexture == NULL)
6020                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6021                                 if (p->fbo_refraction == 0)
6022                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6023                         }
6024                 }
6025                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6026                 {
6027                         if (!p->texture_camera)
6028                                 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);
6029                         if (!p->texture_camera)
6030                                 goto error;
6031                         if (usewaterfbo)
6032                         {
6033                                 if (r_fb.water.depthtexture == NULL)
6034                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6035                                 if (p->fbo_camera == 0)
6036                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6037                         }
6038                 }
6039
6040                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6041                 {
6042                         if (!p->texture_reflection)
6043                                 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);
6044                         if (!p->texture_reflection)
6045                                 goto error;
6046                         if (usewaterfbo)
6047                         {
6048                                 if (r_fb.water.depthtexture == NULL)
6049                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6050                                 if (p->fbo_reflection == 0)
6051                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6052                         }
6053                 }
6054         }
6055
6056         // render views
6057         r_refdef.view = originalview;
6058         r_refdef.view.showdebug = false;
6059         r_refdef.view.width = r_fb.water.waterwidth;
6060         r_refdef.view.height = r_fb.water.waterheight;
6061         r_refdef.view.useclipplane = true;
6062         myview = r_refdef.view;
6063         r_fb.water.renderingscene = true;
6064         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6065         {
6066                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6067                 {
6068                         r_refdef.view = myview;
6069                         if(r_water_scissormode.integer)
6070                         {
6071                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6072                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6073                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6074                         }
6075
6076                         // render reflected scene and copy into texture
6077                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6078                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6079                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6080                         r_refdef.view.clipplane = p->plane;
6081                         // reverse the cullface settings for this render
6082                         r_refdef.view.cullface_front = GL_FRONT;
6083                         r_refdef.view.cullface_back = GL_BACK;
6084                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6085                         {
6086                                 r_refdef.view.usecustompvs = true;
6087                                 if (p->pvsvalid)
6088                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6089                                 else
6090                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6091                         }
6092
6093                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
6094                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6095                         R_ClearScreen(r_refdef.fogenabled);
6096                         if(r_water_scissormode.integer & 2)
6097                                 R_View_UpdateWithScissor(myscissor);
6098                         else
6099                                 R_View_Update();
6100                         R_AnimCache_CacheVisibleEntities();
6101                         if(r_water_scissormode.integer & 1)
6102                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6103                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6104
6105                         if (!p->fbo_reflection)
6106                                 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);
6107                         r_fb.water.hideplayer = false;
6108                 }
6109
6110                 // render the normal view scene and copy into texture
6111                 // (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)
6112                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6113                 {
6114                         r_refdef.view = myview;
6115                         if(r_water_scissormode.integer)
6116                         {
6117                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6118                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6119                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6120                         }
6121
6122                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6123
6124                         r_refdef.view.clipplane = p->plane;
6125                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6126                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6127
6128                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6129                         {
6130                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6131                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6132                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6133                                 R_RenderView_UpdateViewVectors();
6134                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6135                                 {
6136                                         r_refdef.view.usecustompvs = true;
6137                                         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);
6138                                 }
6139                         }
6140
6141                         PlaneClassify(&r_refdef.view.clipplane);
6142
6143                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6144                         R_ClearScreen(r_refdef.fogenabled);
6145                         if(r_water_scissormode.integer & 2)
6146                                 R_View_UpdateWithScissor(myscissor);
6147                         else
6148                                 R_View_Update();
6149                         R_AnimCache_CacheVisibleEntities();
6150                         if(r_water_scissormode.integer & 1)
6151                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6152                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6153
6154                         if (!p->fbo_refraction)
6155                                 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);
6156                         r_fb.water.hideplayer = false;
6157                 }
6158                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6159                 {
6160                         r_refdef.view = myview;
6161
6162                         r_refdef.view.clipplane = p->plane;
6163                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6164                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6165
6166                         r_refdef.view.width = r_fb.water.camerawidth;
6167                         r_refdef.view.height = r_fb.water.cameraheight;
6168                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6169                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6170                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6171                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6172
6173                         if(p->camera_entity)
6174                         {
6175                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6176                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6177                         }
6178
6179                         // note: all of the view is used for displaying... so
6180                         // there is no use in scissoring
6181
6182                         // reverse the cullface settings for this render
6183                         r_refdef.view.cullface_front = GL_FRONT;
6184                         r_refdef.view.cullface_back = GL_BACK;
6185                         // also reverse the view matrix
6186                         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
6187                         R_RenderView_UpdateViewVectors();
6188                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6189                         {
6190                                 r_refdef.view.usecustompvs = true;
6191                                 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);
6192                         }
6193                         
6194                         // camera needs no clipplane
6195                         r_refdef.view.useclipplane = false;
6196
6197                         PlaneClassify(&r_refdef.view.clipplane);
6198
6199                         r_fb.water.hideplayer = false;
6200
6201                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6202                         R_ClearScreen(r_refdef.fogenabled);
6203                         R_View_Update();
6204                         R_AnimCache_CacheVisibleEntities();
6205                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6206
6207                         if (!p->fbo_camera)
6208                                 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);
6209                         r_fb.water.hideplayer = false;
6210                 }
6211
6212         }
6213         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6214         r_fb.water.renderingscene = false;
6215         r_refdef.view = originalview;
6216         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6217         if (!r_fb.water.depthtexture)
6218                 R_ClearScreen(r_refdef.fogenabled);
6219         R_View_Update();
6220         R_AnimCache_CacheVisibleEntities();
6221         goto finish;
6222 error:
6223         r_refdef.view = originalview;
6224         r_fb.water.renderingscene = false;
6225         Cvar_SetValueQuick(&r_water, 0);
6226         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6227 finish:
6228         // lowquality hack, restore cvars
6229         if (qualityreduction > 0)
6230         {
6231                 if (qualityreduction >= 1)
6232                 {
6233                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6234                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6235                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6236                 }
6237                 if (qualityreduction >= 2)
6238                 {
6239                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6240                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6241                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6242                 }
6243         }
6244 }
6245
6246 static void R_Bloom_StartFrame(void)
6247 {
6248         int i;
6249         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6250         int viewwidth, viewheight;
6251         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6252         textype_t textype = TEXTYPE_COLORBUFFER;
6253
6254         switch (vid.renderpath)
6255         {
6256         case RENDERPATH_GL20:
6257                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6258                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6259                 {
6260                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6261                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6262                 }
6263                 break;
6264         case RENDERPATH_GL11:
6265         case RENDERPATH_GL13:
6266         case RENDERPATH_GLES1:
6267         case RENDERPATH_GLES2:
6268         case RENDERPATH_D3D9:
6269         case RENDERPATH_D3D10:
6270         case RENDERPATH_D3D11:
6271                 r_fb.usedepthtextures = false;
6272                 break;
6273         case RENDERPATH_SOFT:
6274                 r_fb.usedepthtextures = true;
6275                 break;
6276         }
6277
6278         if (r_viewscale_fpsscaling.integer)
6279         {
6280                 double actualframetime;
6281                 double targetframetime;
6282                 double adjust;
6283                 actualframetime = r_refdef.lastdrawscreentime;
6284                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6285                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6286                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6287                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6288                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6289                 viewscalefpsadjusted += adjust;
6290                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6291         }
6292         else
6293                 viewscalefpsadjusted = 1.0f;
6294
6295         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6296
6297         switch(vid.renderpath)
6298         {
6299         case RENDERPATH_GL20:
6300         case RENDERPATH_D3D9:
6301         case RENDERPATH_D3D10:
6302         case RENDERPATH_D3D11:
6303         case RENDERPATH_SOFT:
6304         case RENDERPATH_GLES2:
6305                 break;
6306         case RENDERPATH_GL11:
6307         case RENDERPATH_GL13:
6308         case RENDERPATH_GLES1:
6309                 return;
6310         }
6311
6312         // set bloomwidth and bloomheight to the bloom resolution that will be
6313         // used (often less than the screen resolution for faster rendering)
6314         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6315         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6316         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6317         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6318         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6319
6320         // calculate desired texture sizes
6321         if (vid.support.arb_texture_non_power_of_two)
6322         {
6323                 screentexturewidth = vid.width;
6324                 screentextureheight = vid.height;
6325                 bloomtexturewidth = r_fb.bloomwidth;
6326                 bloomtextureheight = r_fb.bloomheight;
6327         }
6328         else
6329         {
6330                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6331                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6332                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6333                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6334         }
6335
6336         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))
6337         {
6338                 Cvar_SetValueQuick(&r_bloom, 0);
6339                 Cvar_SetValueQuick(&r_motionblur, 0);
6340                 Cvar_SetValueQuick(&r_damageblur, 0);
6341         }
6342
6343         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6344          && !r_bloom.integer
6345          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6346          && !useviewfbo
6347          && r_viewscale.value == 1.0f
6348          && !r_viewscale_fpsscaling.integer)
6349                 screentexturewidth = screentextureheight = 0;
6350         if (!r_bloom.integer)
6351                 bloomtexturewidth = bloomtextureheight = 0;
6352
6353         // allocate textures as needed
6354         if (r_fb.screentexturewidth != screentexturewidth
6355          || r_fb.screentextureheight != screentextureheight
6356          || r_fb.bloomtexturewidth != bloomtexturewidth
6357          || r_fb.bloomtextureheight != bloomtextureheight
6358          || r_fb.textype != textype
6359          || useviewfbo != (r_fb.fbo != 0))
6360         {
6361                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6362                 {
6363                         if (r_fb.bloomtexture[i])
6364                                 R_FreeTexture(r_fb.bloomtexture[i]);
6365                         r_fb.bloomtexture[i] = NULL;
6366
6367                         if (r_fb.bloomfbo[i])
6368                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6369                         r_fb.bloomfbo[i] = 0;
6370                 }
6371
6372                 if (r_fb.fbo)
6373                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6374                 r_fb.fbo = 0;
6375
6376                 if (r_fb.colortexture)
6377                         R_FreeTexture(r_fb.colortexture);
6378                 r_fb.colortexture = NULL;
6379
6380                 if (r_fb.depthtexture)
6381                         R_FreeTexture(r_fb.depthtexture);
6382                 r_fb.depthtexture = NULL;
6383
6384                 if (r_fb.ghosttexture)
6385                         R_FreeTexture(r_fb.ghosttexture);
6386                 r_fb.ghosttexture = NULL;
6387
6388                 r_fb.screentexturewidth = screentexturewidth;
6389                 r_fb.screentextureheight = screentextureheight;
6390                 r_fb.bloomtexturewidth = bloomtexturewidth;
6391                 r_fb.bloomtextureheight = bloomtextureheight;
6392                 r_fb.textype = textype;
6393
6394                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6395                 {
6396                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6397                                 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);
6398                         r_fb.ghosttexture_valid = false;
6399                         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);
6400                         if (useviewfbo)
6401                         {
6402                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6403                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6404                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6405                         }
6406                 }
6407
6408                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6409                 {
6410                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6411                         {
6412                                 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);
6413                                 if (useviewfbo)
6414                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6415                         }
6416                 }
6417         }
6418
6419         // bloom texture is a different resolution
6420         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6421         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6422         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6423         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6424         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6425
6426         // set up a texcoord array for the full resolution screen image
6427         // (we have to keep this around to copy back during final render)
6428         r_fb.screentexcoord2f[0] = 0;
6429         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6430         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6431         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6432         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6433         r_fb.screentexcoord2f[5] = 0;
6434         r_fb.screentexcoord2f[6] = 0;
6435         r_fb.screentexcoord2f[7] = 0;
6436
6437         if(r_fb.fbo) 
6438         {
6439                 for (i = 1;i < 8;i += 2)
6440                 {
6441                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6442                 }
6443         }
6444
6445         // set up a texcoord array for the reduced resolution bloom image
6446         // (which will be additive blended over the screen image)
6447         r_fb.bloomtexcoord2f[0] = 0;
6448         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6449         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6450         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6451         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6452         r_fb.bloomtexcoord2f[5] = 0;
6453         r_fb.bloomtexcoord2f[6] = 0;
6454         r_fb.bloomtexcoord2f[7] = 0;
6455
6456         switch(vid.renderpath)
6457         {
6458         case RENDERPATH_GL11:
6459         case RENDERPATH_GL13:
6460         case RENDERPATH_GL20:
6461         case RENDERPATH_SOFT:
6462         case RENDERPATH_GLES1:
6463         case RENDERPATH_GLES2:
6464                 break;
6465         case RENDERPATH_D3D9:
6466         case RENDERPATH_D3D10:
6467         case RENDERPATH_D3D11:
6468                 for (i = 0;i < 4;i++)
6469                 {
6470                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6471                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6472                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6473                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6474                 }
6475                 break;
6476         }
6477
6478         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6479
6480         if (r_fb.fbo)
6481                 r_refdef.view.clear = true;
6482 }
6483
6484 static void R_Bloom_MakeTexture(void)
6485 {
6486         int x, range, dir;
6487         float xoffset, yoffset, r, brighten;
6488         rtexture_t *intex;
6489         float colorscale = r_bloom_colorscale.value;
6490
6491         r_refdef.stats[r_stat_bloom]++;
6492     
6493 #if 0
6494     // this copy is unnecessary since it happens in R_BlendView already
6495         if (!r_fb.fbo)
6496         {
6497                 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);
6498                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6499         }
6500 #endif
6501
6502         // scale down screen texture to the bloom texture size
6503         CHECKGLERROR
6504         r_fb.bloomindex = 0;
6505         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6506         R_SetViewport(&r_fb.bloomviewport);
6507         GL_DepthTest(false);
6508         GL_BlendFunc(GL_ONE, GL_ZERO);
6509         GL_Color(colorscale, colorscale, colorscale, 1);
6510         // 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...
6511         switch(vid.renderpath)
6512         {
6513         case RENDERPATH_GL11:
6514         case RENDERPATH_GL13:
6515         case RENDERPATH_GL20:
6516         case RENDERPATH_GLES1:
6517         case RENDERPATH_GLES2:
6518         case RENDERPATH_SOFT:
6519                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6520                 break;
6521         case RENDERPATH_D3D9:
6522         case RENDERPATH_D3D10:
6523         case RENDERPATH_D3D11:
6524                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6525                 break;
6526         }
6527         // TODO: do boxfilter scale-down in shader?
6528         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6529         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6530         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6531
6532         // we now have a properly scaled bloom image
6533         if (!r_fb.bloomfbo[r_fb.bloomindex])
6534         {
6535                 // copy it into the bloom texture
6536                 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);
6537                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6538         }
6539
6540         // multiply bloom image by itself as many times as desired
6541         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6542         {
6543                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6544                 r_fb.bloomindex ^= 1;
6545                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6546                 x *= 2;
6547                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6548                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6549                 {
6550                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6551                         GL_Color(r,r,r,1); // apply fix factor
6552                 }
6553                 else
6554                 {
6555                         if(x <= 2)
6556                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6557                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6558                         GL_Color(1,1,1,1); // no fix factor supported here
6559                 }
6560                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6561                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6562                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6563                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6564
6565                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6566                 {
6567                         // copy the darkened image to a texture
6568                         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);
6569                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6570                 }
6571         }
6572
6573         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6574         brighten = r_bloom_brighten.value;
6575         brighten = sqrt(brighten);
6576         if(range >= 1)
6577                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6578
6579         for (dir = 0;dir < 2;dir++)
6580         {
6581                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6582                 r_fb.bloomindex ^= 1;
6583                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6584                 // blend on at multiple vertical offsets to achieve a vertical blur
6585                 // TODO: do offset blends using GLSL
6586                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6587                 GL_BlendFunc(GL_ONE, GL_ZERO);
6588                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6589                 for (x = -range;x <= range;x++)
6590                 {
6591                         if (!dir){xoffset = 0;yoffset = x;}
6592                         else {xoffset = x;yoffset = 0;}
6593                         xoffset /= (float)r_fb.bloomtexturewidth;
6594                         yoffset /= (float)r_fb.bloomtextureheight;
6595                         // compute a texcoord array with the specified x and y offset
6596                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6597                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6598                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6599                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6600                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6601                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6602                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6603                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6604                         // this r value looks like a 'dot' particle, fading sharply to
6605                         // black at the edges
6606                         // (probably not realistic but looks good enough)
6607                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6608                         //r = brighten/(range*2+1);
6609                         r = brighten / (range * 2 + 1);
6610                         if(range >= 1)
6611                                 r *= (1 - x*x/(float)(range*range));
6612                         GL_Color(r, r, r, 1);
6613                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6614                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6615                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6616                         GL_BlendFunc(GL_ONE, GL_ONE);
6617                 }
6618
6619                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6620                 {
6621                         // copy the vertically or horizontally blurred bloom view to a texture
6622                         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);
6623                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6624                 }
6625         }
6626 }
6627
6628 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6629 {
6630         unsigned int permutation;
6631         float uservecs[4][4];
6632
6633         R_EntityMatrix(&identitymatrix);
6634
6635         switch (vid.renderpath)
6636         {
6637         case RENDERPATH_GL20:
6638         case RENDERPATH_D3D9:
6639         case RENDERPATH_D3D10:
6640         case RENDERPATH_D3D11:
6641         case RENDERPATH_SOFT:
6642         case RENDERPATH_GLES2:
6643                 permutation =
6644                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6645                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6646                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6647                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6648                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6649
6650                 if (r_fb.colortexture)
6651                 {
6652                         if (!r_fb.fbo)
6653                         {
6654                                 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);
6655                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6656                         }
6657
6658                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6659                         {
6660                                 // declare variables
6661                                 float blur_factor, blur_mouseaccel, blur_velocity;
6662                                 static float blur_average; 
6663                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6664
6665                                 // set a goal for the factoring
6666                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6667                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6668                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6669                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6670                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6671                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6672
6673                                 // from the goal, pick an averaged value between goal and last value
6674                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6675                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6676
6677                                 // enforce minimum amount of blur 
6678                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6679
6680                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6681
6682                                 // calculate values into a standard alpha
6683                                 cl.motionbluralpha = 1 - exp(-
6684                                                 (
6685                                                  (r_motionblur.value * blur_factor / 80)
6686                                                  +
6687                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6688                                                 )
6689                                                 /
6690                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6691                                           );
6692
6693                                 // randomization for the blur value to combat persistent ghosting
6694                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6695                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6696
6697                                 // apply the blur
6698                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6699                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6700                                 {
6701                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6702                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6703                                         switch(vid.renderpath)
6704                                         {
6705                                         case RENDERPATH_GL11:
6706                                         case RENDERPATH_GL13:
6707                                         case RENDERPATH_GL20:
6708                                         case RENDERPATH_GLES1:
6709                                         case RENDERPATH_GLES2:
6710                                         case RENDERPATH_SOFT:
6711                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6712                                                 break;
6713                                         case RENDERPATH_D3D9:
6714                                         case RENDERPATH_D3D10:
6715                                         case RENDERPATH_D3D11:
6716                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6717                                                 break;
6718                                         }
6719                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6720                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6721                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6722                                 }
6723
6724                                 // updates old view angles for next pass
6725                                 VectorCopy(cl.viewangles, blur_oldangles);
6726
6727                                 // copy view into the ghost texture
6728                                 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);
6729                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6730                                 r_fb.ghosttexture_valid = true;
6731                         }
6732                 }
6733                 else
6734                 {
6735                         // no r_fb.colortexture means we're rendering to the real fb
6736                         // we may still have to do view tint...
6737                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6738                         {
6739                                 // apply a color tint to the whole view
6740                                 R_ResetViewRendering2D(0, NULL, NULL);
6741                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6742                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6743                                 R_SetupShader_Generic_NoTexture(false, true);
6744                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6745                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6746                         }
6747                         break; // no screen processing, no bloom, skip it
6748                 }
6749
6750                 if (r_fb.bloomtexture[0])
6751                 {
6752                         // make the bloom texture
6753                         R_Bloom_MakeTexture();
6754                 }
6755
6756 #if _MSC_VER >= 1400
6757 #define sscanf sscanf_s
6758 #endif
6759                 memset(uservecs, 0, sizeof(uservecs));
6760                 if (r_glsl_postprocess_uservec1_enable.integer)
6761                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6762                 if (r_glsl_postprocess_uservec2_enable.integer)
6763                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6764                 if (r_glsl_postprocess_uservec3_enable.integer)
6765                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6766                 if (r_glsl_postprocess_uservec4_enable.integer)
6767                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6768
6769                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6770                 GL_Color(1, 1, 1, 1);
6771                 GL_BlendFunc(GL_ONE, GL_ZERO);
6772
6773                 switch(vid.renderpath)
6774                 {
6775                 case RENDERPATH_GL20:
6776                 case RENDERPATH_GLES2:
6777                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6778                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6779                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6780                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6781                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6782                         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]);
6783                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6784                         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]);
6785                         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]);
6786                         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]);
6787                         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]);
6788                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6789                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6790                         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);
6791                         break;
6792                 case RENDERPATH_D3D9:
6793 #ifdef SUPPORTD3D
6794                         // 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...
6795                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6796                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6797                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6798                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6799                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6800                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6801                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6802                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6803                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6804                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6805                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6806                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6807                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6808                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6809 #endif
6810                         break;
6811                 case RENDERPATH_D3D10:
6812                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6813                         break;
6814                 case RENDERPATH_D3D11:
6815                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6816                         break;
6817                 case RENDERPATH_SOFT:
6818                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6819                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6820                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6821                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6822                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6823                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6824                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6825                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6826                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6827                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6828                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6829                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6830                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6831                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6832                         break;
6833                 default:
6834                         break;
6835                 }
6836                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6837                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6838                 break;
6839         case RENDERPATH_GL11:
6840         case RENDERPATH_GL13:
6841         case RENDERPATH_GLES1:
6842                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6843                 {
6844                         // apply a color tint to the whole view
6845                         R_ResetViewRendering2D(0, NULL, NULL);
6846                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6847                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6848                         R_SetupShader_Generic_NoTexture(false, true);
6849                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6850                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6851                 }
6852                 break;
6853         }
6854 }
6855
6856 matrix4x4_t r_waterscrollmatrix;
6857
6858 void R_UpdateFog(void)
6859 {
6860         // Nehahra fog
6861         if (gamemode == GAME_NEHAHRA)
6862         {
6863                 if (gl_fogenable.integer)
6864                 {
6865                         r_refdef.oldgl_fogenable = true;
6866                         r_refdef.fog_density = gl_fogdensity.value;
6867                         r_refdef.fog_red = gl_fogred.value;
6868                         r_refdef.fog_green = gl_foggreen.value;
6869                         r_refdef.fog_blue = gl_fogblue.value;
6870                         r_refdef.fog_alpha = 1;
6871                         r_refdef.fog_start = 0;
6872                         r_refdef.fog_end = gl_skyclip.value;
6873                         r_refdef.fog_height = 1<<30;
6874                         r_refdef.fog_fadedepth = 128;
6875                 }
6876                 else if (r_refdef.oldgl_fogenable)
6877                 {
6878                         r_refdef.oldgl_fogenable = false;
6879                         r_refdef.fog_density = 0;
6880                         r_refdef.fog_red = 0;
6881                         r_refdef.fog_green = 0;
6882                         r_refdef.fog_blue = 0;
6883                         r_refdef.fog_alpha = 0;
6884                         r_refdef.fog_start = 0;
6885                         r_refdef.fog_end = 0;
6886                         r_refdef.fog_height = 1<<30;
6887                         r_refdef.fog_fadedepth = 128;
6888                 }
6889         }
6890
6891         // fog parms
6892         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6893         r_refdef.fog_start = max(0, r_refdef.fog_start);
6894         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6895
6896         if (r_refdef.fog_density && r_drawfog.integer)
6897         {
6898                 r_refdef.fogenabled = true;
6899                 // this is the point where the fog reaches 0.9986 alpha, which we
6900                 // consider a good enough cutoff point for the texture
6901                 // (0.9986 * 256 == 255.6)
6902                 if (r_fog_exp2.integer)
6903                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6904                 else
6905                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6906                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6907                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6908                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6909                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6910                         R_BuildFogHeightTexture();
6911                 // fog color was already set
6912                 // update the fog texture
6913                 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)
6914                         R_BuildFogTexture();
6915                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6916                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6917         }
6918         else
6919                 r_refdef.fogenabled = false;
6920
6921         // fog color
6922         if (r_refdef.fog_density)
6923         {
6924                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6925                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6926                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6927
6928                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6929                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6930                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6931                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6932
6933                 {
6934                         vec3_t fogvec;
6935                         VectorCopy(r_refdef.fogcolor, fogvec);
6936                         //   color.rgb *= ContrastBoost * SceneBrightness;
6937                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6938                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6939                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6940                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6941                 }
6942         }
6943 }
6944
6945 void R_UpdateVariables(void)
6946 {
6947         R_Textures_Frame();
6948
6949         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6950
6951         r_refdef.farclip = r_farclip_base.value;
6952         if (r_refdef.scene.worldmodel)
6953                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6954         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6955
6956         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6957                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6958         r_refdef.polygonfactor = 0;
6959         r_refdef.polygonoffset = 0;
6960         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6961         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6962
6963         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6964         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6965         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6966         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6967         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6968         if (FAKELIGHT_ENABLED)
6969         {
6970                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6971         }
6972         else if (r_refdef.scene.worldmodel)
6973         {
6974                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6975         }
6976         if (r_showsurfaces.integer)
6977         {
6978                 r_refdef.scene.rtworld = false;
6979                 r_refdef.scene.rtworldshadows = false;
6980                 r_refdef.scene.rtdlight = false;
6981                 r_refdef.scene.rtdlightshadows = false;
6982                 r_refdef.lightmapintensity = 0;
6983         }
6984
6985         r_gpuskeletal = false;
6986         switch(vid.renderpath)
6987         {
6988         case RENDERPATH_GL20:
6989                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6990         case RENDERPATH_D3D9:
6991         case RENDERPATH_D3D10:
6992         case RENDERPATH_D3D11:
6993         case RENDERPATH_SOFT:
6994         case RENDERPATH_GLES2:
6995                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6996                 {
6997                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6998                         {
6999                                 // build GLSL gamma texture
7000 #define RAMPWIDTH 256
7001                                 unsigned short ramp[RAMPWIDTH * 3];
7002                                 unsigned char rampbgr[RAMPWIDTH][4];
7003                                 int i;
7004
7005                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7006
7007                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7008                                 for(i = 0; i < RAMPWIDTH; ++i)
7009                                 {
7010                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7011                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7012                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7013                                         rampbgr[i][3] = 0;
7014                                 }
7015                                 if (r_texture_gammaramps)
7016                                 {
7017                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7018                                 }
7019                                 else
7020                                 {
7021                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7022                                 }
7023                         }
7024                 }
7025                 else
7026                 {
7027                         // remove GLSL gamma texture
7028                 }
7029                 break;
7030         case RENDERPATH_GL11:
7031         case RENDERPATH_GL13:
7032         case RENDERPATH_GLES1:
7033                 break;
7034         }
7035 }
7036
7037 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7038 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7039 /*
7040 ================
7041 R_SelectScene
7042 ================
7043 */
7044 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7045         if( scenetype != r_currentscenetype ) {
7046                 // store the old scenetype
7047                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7048                 r_currentscenetype = scenetype;
7049                 // move in the new scene
7050                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7051         }
7052 }
7053
7054 /*
7055 ================
7056 R_GetScenePointer
7057 ================
7058 */
7059 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7060 {
7061         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7062         if( scenetype == r_currentscenetype ) {
7063                 return &r_refdef.scene;
7064         } else {
7065                 return &r_scenes_store[ scenetype ];
7066         }
7067 }
7068
7069 static int R_SortEntities_Compare(const void *ap, const void *bp)
7070 {
7071         const entity_render_t *a = *(const entity_render_t **)ap;
7072         const entity_render_t *b = *(const entity_render_t **)bp;
7073
7074         // 1. compare model
7075         if(a->model < b->model)
7076                 return -1;
7077         if(a->model > b->model)
7078                 return +1;
7079
7080         // 2. compare skin
7081         // TODO possibly calculate the REAL skinnum here first using
7082         // skinscenes?
7083         if(a->skinnum < b->skinnum)
7084                 return -1;
7085         if(a->skinnum > b->skinnum)
7086                 return +1;
7087
7088         // everything we compared is equal
7089         return 0;
7090 }
7091 static void R_SortEntities(void)
7092 {
7093         // below or equal 2 ents, sorting never gains anything
7094         if(r_refdef.scene.numentities <= 2)
7095                 return;
7096         // sort
7097         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7098 }
7099
7100 /*
7101 ================
7102 R_RenderView
7103 ================
7104 */
7105 int dpsoftrast_test;
7106 extern cvar_t r_shadow_bouncegrid;
7107 void R_RenderView(void)
7108 {
7109         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7110         int fbo;
7111         rtexture_t *depthtexture;
7112         rtexture_t *colortexture;
7113
7114         dpsoftrast_test = r_test.integer;
7115
7116         if (r_timereport_active)
7117                 R_TimeReport("start");
7118         r_textureframe++; // used only by R_GetCurrentTexture
7119         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7120
7121         if(R_CompileShader_CheckStaticParms())
7122                 R_GLSL_Restart_f();
7123
7124         if (!r_drawentities.integer)
7125                 r_refdef.scene.numentities = 0;
7126         else if (r_sortentities.integer)
7127                 R_SortEntities();
7128
7129         R_AnimCache_ClearCache();
7130
7131         /* adjust for stereo display */
7132         if(R_Stereo_Active())
7133         {
7134                 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);
7135                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7136         }
7137
7138         if (r_refdef.view.isoverlay)
7139         {
7140                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7141                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7142                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7143                 R_TimeReport("depthclear");
7144
7145                 r_refdef.view.showdebug = false;
7146
7147                 r_fb.water.enabled = false;
7148                 r_fb.water.numwaterplanes = 0;
7149
7150                 R_RenderScene(0, NULL, NULL);
7151
7152                 r_refdef.view.matrix = originalmatrix;
7153
7154                 CHECKGLERROR
7155                 return;
7156         }
7157
7158         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7159         {
7160                 r_refdef.view.matrix = originalmatrix;
7161                 return;
7162         }
7163
7164         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7165
7166         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7167                 // in sRGB fallback, behave similar to true sRGB: convert this
7168                 // value from linear to sRGB
7169                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7170
7171         R_RenderView_UpdateViewVectors();
7172
7173         R_Shadow_UpdateWorldLightSelection();
7174
7175         R_Bloom_StartFrame();
7176
7177         // apply bloom brightness offset
7178         if(r_fb.bloomtexture[0])
7179                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7180
7181         R_Water_StartFrame();
7182
7183         // now we probably have an fbo to render into
7184         fbo = r_fb.fbo;
7185         depthtexture = r_fb.depthtexture;
7186         colortexture = r_fb.colortexture;
7187
7188         CHECKGLERROR
7189         if (r_timereport_active)
7190                 R_TimeReport("viewsetup");
7191
7192         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7193
7194         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7195         {
7196                 R_ClearScreen(r_refdef.fogenabled);
7197                 if (r_timereport_active)
7198                         R_TimeReport("viewclear");
7199         }
7200         r_refdef.view.clear = true;
7201
7202         r_refdef.view.showdebug = true;
7203
7204         R_View_Update();
7205         if (r_timereport_active)
7206                 R_TimeReport("visibility");
7207
7208         R_AnimCache_CacheVisibleEntities();
7209         if (r_timereport_active)
7210                 R_TimeReport("animcache");
7211
7212         R_Shadow_UpdateBounceGridTexture();
7213         if (r_timereport_active && r_shadow_bouncegrid.integer)
7214                 R_TimeReport("bouncegrid");
7215
7216         r_fb.water.numwaterplanes = 0;
7217         if (r_fb.water.enabled)
7218                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7219
7220         R_RenderScene(fbo, depthtexture, colortexture);
7221         r_fb.water.numwaterplanes = 0;
7222
7223         R_BlendView(fbo, depthtexture, colortexture);
7224         if (r_timereport_active)
7225                 R_TimeReport("blendview");
7226
7227         GL_Scissor(0, 0, vid.width, vid.height);
7228         GL_ScissorTest(false);
7229
7230         r_refdef.view.matrix = originalmatrix;
7231
7232         CHECKGLERROR
7233 }
7234
7235 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7236 {
7237         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7238         {
7239                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7240                 if (r_timereport_active)
7241                         R_TimeReport("waterworld");
7242         }
7243
7244         // don't let sound skip if going slow
7245         if (r_refdef.scene.extraupdate)
7246                 S_ExtraUpdate ();
7247
7248         R_DrawModelsAddWaterPlanes();
7249         if (r_timereport_active)
7250                 R_TimeReport("watermodels");
7251
7252         if (r_fb.water.numwaterplanes)
7253         {
7254                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7255                 if (r_timereport_active)
7256                         R_TimeReport("waterscenes");
7257         }
7258 }
7259
7260 extern cvar_t cl_locs_show;
7261 static void R_DrawLocs(void);
7262 static void R_DrawEntityBBoxes(void);
7263 static void R_DrawModelDecals(void);
7264 extern cvar_t cl_decals_newsystem;
7265 extern qboolean r_shadow_usingdeferredprepass;
7266 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7267 {
7268         qboolean shadowmapping = false;
7269
7270         if (r_timereport_active)
7271                 R_TimeReport("beginscene");
7272
7273         r_refdef.stats[r_stat_renders]++;
7274
7275         R_UpdateFog();
7276
7277         // don't let sound skip if going slow
7278         if (r_refdef.scene.extraupdate)
7279                 S_ExtraUpdate ();
7280
7281         R_MeshQueue_BeginScene();
7282
7283         R_SkyStartFrame();
7284
7285         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);
7286
7287         if (r_timereport_active)
7288                 R_TimeReport("skystartframe");
7289
7290         if (cl.csqc_vidvars.drawworld)
7291         {
7292                 // don't let sound skip if going slow
7293                 if (r_refdef.scene.extraupdate)
7294                         S_ExtraUpdate ();
7295
7296                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7297                 {
7298                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7299                         if (r_timereport_active)
7300                                 R_TimeReport("worldsky");
7301                 }
7302
7303                 if (R_DrawBrushModelsSky() && r_timereport_active)
7304                         R_TimeReport("bmodelsky");
7305
7306                 if (skyrendermasked && skyrenderlater)
7307                 {
7308                         // we have to force off the water clipping plane while rendering sky
7309                         R_SetupView(false, fbo, depthtexture, colortexture);
7310                         R_Sky();
7311                         R_SetupView(true, fbo, depthtexture, colortexture);
7312                         if (r_timereport_active)
7313                                 R_TimeReport("sky");
7314                 }
7315         }
7316
7317         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7318         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7319                 R_Shadow_PrepareModelShadows();
7320         if (r_timereport_active)
7321                 R_TimeReport("preparelights");
7322
7323         if (R_Shadow_ShadowMappingEnabled())
7324                 shadowmapping = true;
7325
7326         if (r_shadow_usingdeferredprepass)
7327                 R_Shadow_DrawPrepass();
7328
7329         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7330         {
7331                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7332                 if (r_timereport_active)
7333                         R_TimeReport("worlddepth");
7334         }
7335         if (r_depthfirst.integer >= 2)
7336         {
7337                 R_DrawModelsDepth();
7338                 if (r_timereport_active)
7339                         R_TimeReport("modeldepth");
7340         }
7341
7342         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7343         {
7344                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7345                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7346                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7347                 // don't let sound skip if going slow
7348                 if (r_refdef.scene.extraupdate)
7349                         S_ExtraUpdate ();
7350         }
7351
7352         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7353         {
7354                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7355                 if (r_timereport_active)
7356                         R_TimeReport("world");
7357         }
7358
7359         // don't let sound skip if going slow
7360         if (r_refdef.scene.extraupdate)
7361                 S_ExtraUpdate ();
7362
7363         R_DrawModels();
7364         if (r_timereport_active)
7365                 R_TimeReport("models");
7366
7367         // don't let sound skip if going slow
7368         if (r_refdef.scene.extraupdate)
7369                 S_ExtraUpdate ();
7370
7371         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7372         {
7373                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7374                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7375                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7376                 // don't let sound skip if going slow
7377                 if (r_refdef.scene.extraupdate)
7378                         S_ExtraUpdate ();
7379         }
7380
7381         if (!r_shadow_usingdeferredprepass)
7382         {
7383                 R_Shadow_DrawLights();
7384                 if (r_timereport_active)
7385                         R_TimeReport("rtlights");
7386         }
7387
7388         // don't let sound skip if going slow
7389         if (r_refdef.scene.extraupdate)
7390                 S_ExtraUpdate ();
7391
7392         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7393         {
7394                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7395                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7396                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7397                 // don't let sound skip if going slow
7398                 if (r_refdef.scene.extraupdate)
7399                         S_ExtraUpdate ();
7400         }
7401
7402         if (cl.csqc_vidvars.drawworld)
7403         {
7404                 if (cl_decals_newsystem.integer)
7405                 {
7406                         R_DrawModelDecals();
7407                         if (r_timereport_active)
7408                                 R_TimeReport("modeldecals");
7409                 }
7410                 else
7411                 {
7412                         R_DrawDecals();
7413                         if (r_timereport_active)
7414                                 R_TimeReport("decals");
7415                 }
7416
7417                 R_DrawParticles();
7418                 if (r_timereport_active)
7419                         R_TimeReport("particles");
7420
7421                 R_DrawExplosions();
7422                 if (r_timereport_active)
7423                         R_TimeReport("explosions");
7424
7425                 R_DrawLightningBeams();
7426                 if (r_timereport_active)
7427                         R_TimeReport("lightning");
7428         }
7429
7430         if (cl.csqc_loaded)
7431                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7432
7433         if (r_refdef.view.showdebug)
7434         {
7435                 if (cl_locs_show.integer)
7436                 {
7437                         R_DrawLocs();
7438                         if (r_timereport_active)
7439                                 R_TimeReport("showlocs");
7440                 }
7441
7442                 if (r_drawportals.integer)
7443                 {
7444                         R_DrawPortals();
7445                         if (r_timereport_active)
7446                                 R_TimeReport("portals");
7447                 }
7448
7449                 if (r_showbboxes.value > 0)
7450                 {
7451                         R_DrawEntityBBoxes();
7452                         if (r_timereport_active)
7453                                 R_TimeReport("bboxes");
7454                 }
7455         }
7456
7457         if (r_transparent.integer)
7458         {
7459                 R_MeshQueue_RenderTransparent();
7460                 if (r_timereport_active)
7461                         R_TimeReport("drawtrans");
7462         }
7463
7464         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))
7465         {
7466                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7467                 if (r_timereport_active)
7468                         R_TimeReport("worlddebug");
7469                 R_DrawModelsDebug();
7470                 if (r_timereport_active)
7471                         R_TimeReport("modeldebug");
7472         }
7473
7474         if (cl.csqc_vidvars.drawworld)
7475         {
7476                 R_Shadow_DrawCoronas();
7477                 if (r_timereport_active)
7478                         R_TimeReport("coronas");
7479         }
7480
7481 #if 0
7482         {
7483                 GL_DepthTest(false);
7484                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7485                 GL_Color(1, 1, 1, 1);
7486                 qglBegin(GL_POLYGON);
7487                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7488                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7489                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7490                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7491                 qglEnd();
7492                 qglBegin(GL_POLYGON);
7493                 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]);
7494                 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]);
7495                 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]);
7496                 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]);
7497                 qglEnd();
7498                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7499         }
7500 #endif
7501
7502         // don't let sound skip if going slow
7503         if (r_refdef.scene.extraupdate)
7504                 S_ExtraUpdate ();
7505 }
7506
7507 static const unsigned short bboxelements[36] =
7508 {
7509         5, 1, 3, 5, 3, 7,
7510         6, 2, 0, 6, 0, 4,
7511         7, 3, 2, 7, 2, 6,
7512         4, 0, 1, 4, 1, 5,
7513         4, 5, 7, 4, 7, 6,
7514         1, 0, 2, 1, 2, 3,
7515 };
7516
7517 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7518 {
7519         int i;
7520         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7521
7522         RSurf_ActiveWorldEntity();
7523
7524         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7525         GL_DepthMask(false);
7526         GL_DepthRange(0, 1);
7527         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7528 //      R_Mesh_ResetTextureState();
7529
7530         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7531         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7532         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7533         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7534         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7535         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7536         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7537         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7538         R_FillColors(color4f, 8, cr, cg, cb, ca);
7539         if (r_refdef.fogenabled)
7540         {
7541                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7542                 {
7543                         f1 = RSurf_FogVertex(v);
7544                         f2 = 1 - f1;
7545                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7546                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7547                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7548                 }
7549         }
7550         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7551         R_Mesh_ResetTextureState();
7552         R_SetupShader_Generic_NoTexture(false, false);
7553         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7554 }
7555
7556 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7557 {
7558         prvm_prog_t *prog = SVVM_prog;
7559         int i;
7560         float color[4];
7561         prvm_edict_t *edict;
7562
7563         // this function draws bounding boxes of server entities
7564         if (!sv.active)
7565                 return;
7566
7567         GL_CullFace(GL_NONE);
7568         R_SetupShader_Generic_NoTexture(false, false);
7569
7570         for (i = 0;i < numsurfaces;i++)
7571         {
7572                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7573                 switch ((int)PRVM_serveredictfloat(edict, solid))
7574                 {
7575                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7576                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7577                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7578                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7579                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7580                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7581                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7582                 }
7583                 color[3] *= r_showbboxes.value;
7584                 color[3] = bound(0, color[3], 1);
7585                 GL_DepthTest(!r_showdisabledepthtest.integer);
7586                 GL_CullFace(r_refdef.view.cullface_front);
7587                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7588         }
7589 }
7590
7591 static void R_DrawEntityBBoxes(void)
7592 {
7593         int i;
7594         prvm_edict_t *edict;
7595         vec3_t center;
7596         prvm_prog_t *prog = SVVM_prog;
7597
7598         // this function draws bounding boxes of server entities
7599         if (!sv.active)
7600                 return;
7601
7602         for (i = 0;i < prog->num_edicts;i++)
7603         {
7604                 edict = PRVM_EDICT_NUM(i);
7605                 if (edict->priv.server->free)
7606                         continue;
7607                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7608                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7609                         continue;
7610                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7611                         continue;
7612                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7613                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7614         }
7615 }
7616
7617 static const int nomodelelement3i[24] =
7618 {
7619         5, 2, 0,
7620         5, 1, 2,
7621         5, 0, 3,
7622         5, 3, 1,
7623         0, 2, 4,
7624         2, 1, 4,
7625         3, 0, 4,
7626         1, 3, 4
7627 };
7628
7629 static const unsigned short nomodelelement3s[24] =
7630 {
7631         5, 2, 0,
7632         5, 1, 2,
7633         5, 0, 3,
7634         5, 3, 1,
7635         0, 2, 4,
7636         2, 1, 4,
7637         3, 0, 4,
7638         1, 3, 4
7639 };
7640
7641 static const float nomodelvertex3f[6*3] =
7642 {
7643         -16,   0,   0,
7644          16,   0,   0,
7645           0, -16,   0,
7646           0,  16,   0,
7647           0,   0, -16,
7648           0,   0,  16
7649 };
7650
7651 static const float nomodelcolor4f[6*4] =
7652 {
7653         0.0f, 0.0f, 0.5f, 1.0f,
7654         0.0f, 0.0f, 0.5f, 1.0f,
7655         0.0f, 0.5f, 0.0f, 1.0f,
7656         0.0f, 0.5f, 0.0f, 1.0f,
7657         0.5f, 0.0f, 0.0f, 1.0f,
7658         0.5f, 0.0f, 0.0f, 1.0f
7659 };
7660
7661 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7662 {
7663         int i;
7664         float f1, f2, *c;
7665         float color4f[6*4];
7666
7667         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);
7668
7669         // this is only called once per entity so numsurfaces is always 1, and
7670         // surfacelist is always {0}, so this code does not handle batches
7671
7672         if (rsurface.ent_flags & RENDER_ADDITIVE)
7673         {
7674                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7675                 GL_DepthMask(false);
7676         }
7677         else if (rsurface.colormod[3] < 1)
7678         {
7679                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7680                 GL_DepthMask(false);
7681         }
7682         else
7683         {
7684                 GL_BlendFunc(GL_ONE, GL_ZERO);
7685                 GL_DepthMask(true);
7686         }
7687         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7688         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7689         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7690         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7691         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7692         for (i = 0, c = color4f;i < 6;i++, c += 4)
7693         {
7694                 c[0] *= rsurface.colormod[0];
7695                 c[1] *= rsurface.colormod[1];
7696                 c[2] *= rsurface.colormod[2];
7697                 c[3] *= rsurface.colormod[3];
7698         }
7699         if (r_refdef.fogenabled)
7700         {
7701                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7702                 {
7703                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7704                         f2 = 1 - f1;
7705                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7706                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7707                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7708                 }
7709         }
7710 //      R_Mesh_ResetTextureState();
7711         R_SetupShader_Generic_NoTexture(false, false);
7712         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7713         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7714 }
7715
7716 void R_DrawNoModel(entity_render_t *ent)
7717 {
7718         vec3_t org;
7719         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7720         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7721                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7722         else
7723                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7724 }
7725
7726 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7727 {
7728         vec3_t right1, right2, diff, normal;
7729
7730         VectorSubtract (org2, org1, normal);
7731
7732         // calculate 'right' vector for start
7733         VectorSubtract (r_refdef.view.origin, org1, diff);
7734         CrossProduct (normal, diff, right1);
7735         VectorNormalize (right1);
7736
7737         // calculate 'right' vector for end
7738         VectorSubtract (r_refdef.view.origin, org2, diff);
7739         CrossProduct (normal, diff, right2);
7740         VectorNormalize (right2);
7741
7742         vert[ 0] = org1[0] + width * right1[0];
7743         vert[ 1] = org1[1] + width * right1[1];
7744         vert[ 2] = org1[2] + width * right1[2];
7745         vert[ 3] = org1[0] - width * right1[0];
7746         vert[ 4] = org1[1] - width * right1[1];
7747         vert[ 5] = org1[2] - width * right1[2];
7748         vert[ 6] = org2[0] - width * right2[0];
7749         vert[ 7] = org2[1] - width * right2[1];
7750         vert[ 8] = org2[2] - width * right2[2];
7751         vert[ 9] = org2[0] + width * right2[0];
7752         vert[10] = org2[1] + width * right2[1];
7753         vert[11] = org2[2] + width * right2[2];
7754 }
7755
7756 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)
7757 {
7758         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7759         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7760         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7761         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7762         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7763         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7764         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7765         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7766         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7767         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7768         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7769         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7770 }
7771
7772 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7773 {
7774         int i;
7775         float *vertex3f;
7776         float v[3];
7777         VectorSet(v, x, y, z);
7778         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7779                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7780                         break;
7781         if (i == mesh->numvertices)
7782         {
7783                 if (mesh->numvertices < mesh->maxvertices)
7784                 {
7785                         VectorCopy(v, vertex3f);
7786                         mesh->numvertices++;
7787                 }
7788                 return mesh->numvertices;
7789         }
7790         else
7791                 return i;
7792 }
7793
7794 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7795 {
7796         int i;
7797         int *e, element[3];
7798         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7799         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7800         e = mesh->element3i + mesh->numtriangles * 3;
7801         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7802         {
7803                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7804                 if (mesh->numtriangles < mesh->maxtriangles)
7805                 {
7806                         *e++ = element[0];
7807                         *e++ = element[1];
7808                         *e++ = element[2];
7809                         mesh->numtriangles++;
7810                 }
7811                 element[1] = element[2];
7812         }
7813 }
7814
7815 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7816 {
7817         int i;
7818         int *e, element[3];
7819         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7820         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7821         e = mesh->element3i + mesh->numtriangles * 3;
7822         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7823         {
7824                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7825                 if (mesh->numtriangles < mesh->maxtriangles)
7826                 {
7827                         *e++ = element[0];
7828                         *e++ = element[1];
7829                         *e++ = element[2];
7830                         mesh->numtriangles++;
7831                 }
7832                 element[1] = element[2];
7833         }
7834 }
7835
7836 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7837 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7838 {
7839         int planenum, planenum2;
7840         int w;
7841         int tempnumpoints;
7842         mplane_t *plane, *plane2;
7843         double maxdist;
7844         double temppoints[2][256*3];
7845         // figure out how large a bounding box we need to properly compute this brush
7846         maxdist = 0;
7847         for (w = 0;w < numplanes;w++)
7848                 maxdist = max(maxdist, fabs(planes[w].dist));
7849         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7850         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7851         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7852         {
7853                 w = 0;
7854                 tempnumpoints = 4;
7855                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7856                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7857                 {
7858                         if (planenum2 == planenum)
7859                                 continue;
7860                         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);
7861                         w = !w;
7862                 }
7863                 if (tempnumpoints < 3)
7864                         continue;
7865                 // generate elements forming a triangle fan for this polygon
7866                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7867         }
7868 }
7869
7870 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)
7871 {
7872         texturelayer_t *layer;
7873         layer = t->currentlayers + t->currentnumlayers++;
7874         layer->type = type;
7875         layer->depthmask = depthmask;
7876         layer->blendfunc1 = blendfunc1;
7877         layer->blendfunc2 = blendfunc2;
7878         layer->texture = texture;
7879         layer->texmatrix = *matrix;
7880         layer->color[0] = r;
7881         layer->color[1] = g;
7882         layer->color[2] = b;
7883         layer->color[3] = a;
7884 }
7885
7886 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7887 {
7888         if(parms[0] == 0 && parms[1] == 0)
7889                 return false;
7890         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7891                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7892                         return false;
7893         return true;
7894 }
7895
7896 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7897 {
7898         double index, f;
7899         index = parms[2] + rsurface.shadertime * parms[3];
7900         index -= floor(index);
7901         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7902         {
7903         default:
7904         case Q3WAVEFUNC_NONE:
7905         case Q3WAVEFUNC_NOISE:
7906         case Q3WAVEFUNC_COUNT:
7907                 f = 0;
7908                 break;
7909         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7910         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7911         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7912         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7913         case Q3WAVEFUNC_TRIANGLE:
7914                 index *= 4;
7915                 f = index - floor(index);
7916                 if (index < 1)
7917                 {
7918                         // f = f;
7919                 }
7920                 else if (index < 2)
7921                         f = 1 - f;
7922                 else if (index < 3)
7923                         f = -f;
7924                 else
7925                         f = -(1 - f);
7926                 break;
7927         }
7928         f = parms[0] + parms[1] * f;
7929         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7930                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7931         return (float) f;
7932 }
7933
7934 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7935 {
7936         int w, h, idx;
7937         double f;
7938         double offsetd[2];
7939         float tcmat[12];
7940         matrix4x4_t matrix, temp;
7941         switch(tcmod->tcmod)
7942         {
7943                 case Q3TCMOD_COUNT:
7944                 case Q3TCMOD_NONE:
7945                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7946                                 matrix = r_waterscrollmatrix;
7947                         else
7948                                 matrix = identitymatrix;
7949                         break;
7950                 case Q3TCMOD_ENTITYTRANSLATE:
7951                         // this is used in Q3 to allow the gamecode to control texcoord
7952                         // scrolling on the entity, which is not supported in darkplaces yet.
7953                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7954                         break;
7955                 case Q3TCMOD_ROTATE:
7956                         f = tcmod->parms[0] * rsurface.shadertime;
7957                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7958                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7959                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7960                         break;
7961                 case Q3TCMOD_SCALE:
7962                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7963                         break;
7964                 case Q3TCMOD_SCROLL:
7965                         // extra care is needed because of precision breakdown with large values of time
7966                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7967                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7968                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7969                         break;
7970                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7971                         w = (int) tcmod->parms[0];
7972                         h = (int) tcmod->parms[1];
7973                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7974                         f = f - floor(f);
7975                         idx = (int) floor(f * w * h);
7976                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7977                         break;
7978                 case Q3TCMOD_STRETCH:
7979                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7980                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7981                         break;
7982                 case Q3TCMOD_TRANSFORM:
7983                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7984                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7985                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7986                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7987                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7988                         break;
7989                 case Q3TCMOD_TURBULENT:
7990                         // this is handled in the RSurf_PrepareVertices function
7991                         matrix = identitymatrix;
7992                         break;
7993         }
7994         temp = *texmatrix;
7995         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7996 }
7997
7998 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7999 {
8000         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8001         char name[MAX_QPATH];
8002         skinframe_t *skinframe;
8003         unsigned char pixels[296*194];
8004         strlcpy(cache->name, skinname, sizeof(cache->name));
8005         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8006         if (developer_loading.integer)
8007                 Con_Printf("loading %s\n", name);
8008         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8009         if (!skinframe || !skinframe->base)
8010         {
8011                 unsigned char *f;
8012                 fs_offset_t filesize;
8013                 skinframe = NULL;
8014                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8015                 if (f)
8016                 {
8017                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8018                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8019                         Mem_Free(f);
8020                 }
8021         }
8022         cache->skinframe = skinframe;
8023 }
8024
8025 texture_t *R_GetCurrentTexture(texture_t *t)
8026 {
8027         int i;
8028         const entity_render_t *ent = rsurface.entity;
8029         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8030         q3shaderinfo_layer_tcmod_t *tcmod;
8031
8032         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8033                 return t->currentframe;
8034         t->update_lastrenderframe = r_textureframe;
8035         t->update_lastrenderentity = (void *)ent;
8036
8037         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8038                 t->camera_entity = ent->entitynumber;
8039         else
8040                 t->camera_entity = 0;
8041
8042         // switch to an alternate material if this is a q1bsp animated material
8043         {
8044                 texture_t *texture = t;
8045                 int s = rsurface.ent_skinnum;
8046                 if ((unsigned int)s >= (unsigned int)model->numskins)
8047                         s = 0;
8048                 if (model->skinscenes)
8049                 {
8050                         if (model->skinscenes[s].framecount > 1)
8051                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8052                         else
8053                                 s = model->skinscenes[s].firstframe;
8054                 }
8055                 if (s > 0)
8056                         t = t + s * model->num_surfaces;
8057                 if (t->animated)
8058                 {
8059                         // use an alternate animation if the entity's frame is not 0,
8060                         // and only if the texture has an alternate animation
8061                         if (rsurface.ent_alttextures && t->anim_total[1])
8062                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8063                         else
8064                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8065                 }
8066                 texture->currentframe = t;
8067         }
8068
8069         // update currentskinframe to be a qw skin or animation frame
8070         if (rsurface.ent_qwskin >= 0)
8071         {
8072                 i = rsurface.ent_qwskin;
8073                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8074                 {
8075                         r_qwskincache_size = cl.maxclients;
8076                         if (r_qwskincache)
8077                                 Mem_Free(r_qwskincache);
8078                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8079                 }
8080                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8081                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8082                 t->currentskinframe = r_qwskincache[i].skinframe;
8083                 if (t->currentskinframe == NULL)
8084                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8085         }
8086         else if (t->numskinframes >= 2)
8087                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8088         if (t->backgroundnumskinframes >= 2)
8089                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8090
8091         t->currentmaterialflags = t->basematerialflags;
8092         t->currentalpha = rsurface.colormod[3];
8093         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8094                 t->currentalpha *= r_wateralpha.value;
8095         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8096                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8097         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8098                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8099         if (!(rsurface.ent_flags & RENDER_LIGHT))
8100                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8101         else if (FAKELIGHT_ENABLED)
8102         {
8103                 // no modellight if using fakelight for the map
8104         }
8105         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8106         {
8107                 // pick a model lighting mode
8108                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8109                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8110                 else
8111                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8112         }
8113         if (rsurface.ent_flags & RENDER_ADDITIVE)
8114                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8115         else if (t->currentalpha < 1)
8116                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8117         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8118         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8119                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8120         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8121                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8122         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8123                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8124         if (t->backgroundnumskinframes)
8125                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8126         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8127         {
8128                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8129                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8130         }
8131         else
8132                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8133         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8134         {
8135                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8136                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8137         }
8138         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8139                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8140
8141         // there is no tcmod
8142         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8143         {
8144                 t->currenttexmatrix = r_waterscrollmatrix;
8145                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8146         }
8147         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8148         {
8149                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8150                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8151         }
8152
8153         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8154                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8155         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8156                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8157
8158         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8159         if (t->currentskinframe->qpixels)
8160                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8161         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8162         if (!t->basetexture)
8163                 t->basetexture = r_texture_notexture;
8164         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8165         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8166         t->nmaptexture = t->currentskinframe->nmap;
8167         if (!t->nmaptexture)
8168                 t->nmaptexture = r_texture_blanknormalmap;
8169         t->glosstexture = r_texture_black;
8170         t->glowtexture = t->currentskinframe->glow;
8171         t->fogtexture = t->currentskinframe->fog;
8172         t->reflectmasktexture = t->currentskinframe->reflect;
8173         if (t->backgroundnumskinframes)
8174         {
8175                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8176                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8177                 t->backgroundglosstexture = r_texture_black;
8178                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8179                 if (!t->backgroundnmaptexture)
8180                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8181                 // make sure that if glow is going to be used, both textures are not NULL
8182                 if (!t->backgroundglowtexture && t->glowtexture)
8183                         t->backgroundglowtexture = r_texture_black;
8184                 if (!t->glowtexture && t->backgroundglowtexture)
8185                         t->glowtexture = r_texture_black;
8186         }
8187         else
8188         {
8189                 t->backgroundbasetexture = r_texture_white;
8190                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8191                 t->backgroundglosstexture = r_texture_black;
8192                 t->backgroundglowtexture = NULL;
8193         }
8194         t->specularpower = r_shadow_glossexponent.value;
8195         // TODO: store reference values for these in the texture?
8196         t->specularscale = 0;
8197         if (r_shadow_gloss.integer > 0)
8198         {
8199                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8200                 {
8201                         if (r_shadow_glossintensity.value > 0)
8202                         {
8203                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8204                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8205                                 t->specularscale = r_shadow_glossintensity.value;
8206                         }
8207                 }
8208                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8209                 {
8210                         t->glosstexture = r_texture_white;
8211                         t->backgroundglosstexture = r_texture_white;
8212                         t->specularscale = r_shadow_gloss2intensity.value;
8213                         t->specularpower = r_shadow_gloss2exponent.value;
8214                 }
8215         }
8216         t->specularscale *= t->specularscalemod;
8217         t->specularpower *= t->specularpowermod;
8218         t->rtlightambient = 0;
8219
8220         // lightmaps mode looks bad with dlights using actual texturing, so turn
8221         // off the colormap and glossmap, but leave the normalmap on as it still
8222         // accurately represents the shading involved
8223         if (gl_lightmaps.integer)
8224         {
8225                 t->basetexture = r_texture_grey128;
8226                 t->pantstexture = r_texture_black;
8227                 t->shirttexture = r_texture_black;
8228                 if (gl_lightmaps.integer < 2)
8229                         t->nmaptexture = r_texture_blanknormalmap;
8230                 t->glosstexture = r_texture_black;
8231                 t->glowtexture = NULL;
8232                 t->fogtexture = NULL;
8233                 t->reflectmasktexture = NULL;
8234                 t->backgroundbasetexture = NULL;
8235                 if (gl_lightmaps.integer < 2)
8236                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8237                 t->backgroundglosstexture = r_texture_black;
8238                 t->backgroundglowtexture = NULL;
8239                 t->specularscale = 0;
8240                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8241         }
8242
8243         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8244         VectorClear(t->dlightcolor);
8245         t->currentnumlayers = 0;
8246         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8247         {
8248                 int blendfunc1, blendfunc2;
8249                 qboolean depthmask;
8250                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8251                 {
8252                         blendfunc1 = GL_SRC_ALPHA;
8253                         blendfunc2 = GL_ONE;
8254                 }
8255                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8256                 {
8257                         blendfunc1 = GL_SRC_ALPHA;
8258                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8259                 }
8260                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8261                 {
8262                         blendfunc1 = t->customblendfunc[0];
8263                         blendfunc2 = t->customblendfunc[1];
8264                 }
8265                 else
8266                 {
8267                         blendfunc1 = GL_ONE;
8268                         blendfunc2 = GL_ZERO;
8269                 }
8270                 // don't colormod evilblend textures
8271                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8272                         VectorSet(t->lightmapcolor, 1, 1, 1);
8273                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8274                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8275                 {
8276                         // fullbright is not affected by r_refdef.lightmapintensity
8277                         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]);
8278                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8279                                 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]);
8280                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8281                                 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]);
8282                 }
8283                 else
8284                 {
8285                         vec3_t ambientcolor;
8286                         float colorscale;
8287                         // set the color tint used for lights affecting this surface
8288                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8289                         colorscale = 2;
8290                         // q3bsp has no lightmap updates, so the lightstylevalue that
8291                         // would normally be baked into the lightmap must be
8292                         // applied to the color
8293                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8294                         if (model->type == mod_brushq3)
8295                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8296                         colorscale *= r_refdef.lightmapintensity;
8297                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8298                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8299                         // basic lit geometry
8300                         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]);
8301                         // add pants/shirt if needed
8302                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8303                                 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]);
8304                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8305                                 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]);
8306                         // now add ambient passes if needed
8307                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8308                         {
8309                                 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]);
8310                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8311                                         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]);
8312                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8313                                         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]);
8314                         }
8315                 }
8316                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8317                         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]);
8318                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8319                 {
8320                         // if this is opaque use alpha blend which will darken the earlier
8321                         // passes cheaply.
8322                         //
8323                         // if this is an alpha blended material, all the earlier passes
8324                         // were darkened by fog already, so we only need to add the fog
8325                         // color ontop through the fog mask texture
8326                         //
8327                         // if this is an additive blended material, all the earlier passes
8328                         // were darkened by fog already, and we should not add fog color
8329                         // (because the background was not darkened, there is no fog color
8330                         // that was lost behind it).
8331                         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]);
8332                 }
8333         }
8334
8335         return t->currentframe;
8336 }
8337
8338 rsurfacestate_t rsurface;
8339
8340 void RSurf_ActiveWorldEntity(void)
8341 {
8342         dp_model_t *model = r_refdef.scene.worldmodel;
8343         //if (rsurface.entity == r_refdef.scene.worldentity)
8344         //      return;
8345         rsurface.entity = r_refdef.scene.worldentity;
8346         rsurface.skeleton = NULL;
8347         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8348         rsurface.ent_skinnum = 0;
8349         rsurface.ent_qwskin = -1;
8350         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8351         rsurface.shadertime = r_refdef.scene.time;
8352         rsurface.matrix = identitymatrix;
8353         rsurface.inversematrix = identitymatrix;
8354         rsurface.matrixscale = 1;
8355         rsurface.inversematrixscale = 1;
8356         R_EntityMatrix(&identitymatrix);
8357         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8358         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8359         rsurface.fograngerecip = r_refdef.fograngerecip;
8360         rsurface.fogheightfade = r_refdef.fogheightfade;
8361         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8362         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8363         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8364         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8365         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8366         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8367         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8368         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8369         rsurface.colormod[3] = 1;
8370         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);
8371         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8372         rsurface.frameblend[0].lerp = 1;
8373         rsurface.ent_alttextures = false;
8374         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8375         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8376         rsurface.entityskeletaltransform3x4 = NULL;
8377         rsurface.entityskeletaltransform3x4buffer = NULL;
8378         rsurface.entityskeletaltransform3x4offset = 0;
8379         rsurface.entityskeletaltransform3x4size = 0;;
8380         rsurface.entityskeletalnumtransforms = 0;
8381         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8382         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8383         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8384         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8385         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8386         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8387         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8388         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8389         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8390         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8391         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8392         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8393         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8394         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8395         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8396         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8397         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8398         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8399         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8400         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8401         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8402         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8403         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8404         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8405         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8406         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8407         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8408         rsurface.modelelement3i = model->surfmesh.data_element3i;
8409         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8410         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8411         rsurface.modelelement3s = model->surfmesh.data_element3s;
8412         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8413         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8414         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8415         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8416         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8417         rsurface.modelsurfaces = model->data_surfaces;
8418         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8419         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8420         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8421         rsurface.modelgeneratedvertex = false;
8422         rsurface.batchgeneratedvertex = false;
8423         rsurface.batchfirstvertex = 0;
8424         rsurface.batchnumvertices = 0;
8425         rsurface.batchfirsttriangle = 0;
8426         rsurface.batchnumtriangles = 0;
8427         rsurface.batchvertex3f  = NULL;
8428         rsurface.batchvertex3f_vertexbuffer = NULL;
8429         rsurface.batchvertex3f_bufferoffset = 0;
8430         rsurface.batchsvector3f = NULL;
8431         rsurface.batchsvector3f_vertexbuffer = NULL;
8432         rsurface.batchsvector3f_bufferoffset = 0;
8433         rsurface.batchtvector3f = NULL;
8434         rsurface.batchtvector3f_vertexbuffer = NULL;
8435         rsurface.batchtvector3f_bufferoffset = 0;
8436         rsurface.batchnormal3f  = NULL;
8437         rsurface.batchnormal3f_vertexbuffer = NULL;
8438         rsurface.batchnormal3f_bufferoffset = 0;
8439         rsurface.batchlightmapcolor4f = NULL;
8440         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8441         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8442         rsurface.batchtexcoordtexture2f = NULL;
8443         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8444         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8445         rsurface.batchtexcoordlightmap2f = NULL;
8446         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8447         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8448         rsurface.batchskeletalindex4ub = NULL;
8449         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8450         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8451         rsurface.batchskeletalweight4ub = NULL;
8452         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8453         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8454         rsurface.batchvertexmesh = NULL;
8455         rsurface.batchvertexmesh_vertexbuffer = NULL;
8456         rsurface.batchvertexmesh_bufferoffset = 0;
8457         rsurface.batchelement3i = NULL;
8458         rsurface.batchelement3i_indexbuffer = NULL;
8459         rsurface.batchelement3i_bufferoffset = 0;
8460         rsurface.batchelement3s = NULL;
8461         rsurface.batchelement3s_indexbuffer = NULL;
8462         rsurface.batchelement3s_bufferoffset = 0;
8463         rsurface.passcolor4f = NULL;
8464         rsurface.passcolor4f_vertexbuffer = NULL;
8465         rsurface.passcolor4f_bufferoffset = 0;
8466         rsurface.forcecurrenttextureupdate = false;
8467 }
8468
8469 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8470 {
8471         dp_model_t *model = ent->model;
8472         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8473         //      return;
8474         rsurface.entity = (entity_render_t *)ent;
8475         rsurface.skeleton = ent->skeleton;
8476         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8477         rsurface.ent_skinnum = ent->skinnum;
8478         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;
8479         rsurface.ent_flags = ent->flags;
8480         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8481         rsurface.matrix = ent->matrix;
8482         rsurface.inversematrix = ent->inversematrix;
8483         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8484         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8485         R_EntityMatrix(&rsurface.matrix);
8486         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8487         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8488         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8489         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8490         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8491         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8492         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8493         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8494         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8495         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8496         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8497         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8498         rsurface.colormod[3] = ent->alpha;
8499         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8500         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8501         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8502         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8503         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8504         if (ent->model->brush.submodel && !prepass)
8505         {
8506                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8507                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8508         }
8509         // if the animcache code decided it should use the shader path, skip the deform step
8510         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8511         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8512         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8513         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8514         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8515         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8516         {
8517                 if (ent->animcache_vertex3f)
8518                 {
8519                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8520                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8521                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8522                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8523                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8524                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8525                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8526                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8527                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8528                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8529                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8530                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8531                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8532                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8533                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8534                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8535                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8536                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8537                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8538                 }
8539                 else if (wanttangents)
8540                 {
8541                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8542                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8543                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8544                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8545                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8546                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8547                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8548                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8549                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8550                         rsurface.modelvertexmesh = NULL;
8551                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8552                         rsurface.modelvertexmesh_bufferoffset = 0;
8553                         rsurface.modelvertex3f_vertexbuffer = NULL;
8554                         rsurface.modelvertex3f_bufferoffset = 0;
8555                         rsurface.modelvertex3f_vertexbuffer = 0;
8556                         rsurface.modelvertex3f_bufferoffset = 0;
8557                         rsurface.modelsvector3f_vertexbuffer = 0;
8558                         rsurface.modelsvector3f_bufferoffset = 0;
8559                         rsurface.modeltvector3f_vertexbuffer = 0;
8560                         rsurface.modeltvector3f_bufferoffset = 0;
8561                         rsurface.modelnormal3f_vertexbuffer = 0;
8562                         rsurface.modelnormal3f_bufferoffset = 0;
8563                 }
8564                 else if (wantnormals)
8565                 {
8566                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8567                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8568                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8569                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8570                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8571                         rsurface.modelsvector3f = NULL;
8572                         rsurface.modeltvector3f = NULL;
8573                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8574                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8575                         rsurface.modelvertexmesh = NULL;
8576                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8577                         rsurface.modelvertexmesh_bufferoffset = 0;
8578                         rsurface.modelvertex3f_vertexbuffer = NULL;
8579                         rsurface.modelvertex3f_bufferoffset = 0;
8580                         rsurface.modelvertex3f_vertexbuffer = 0;
8581                         rsurface.modelvertex3f_bufferoffset = 0;
8582                         rsurface.modelsvector3f_vertexbuffer = 0;
8583                         rsurface.modelsvector3f_bufferoffset = 0;
8584                         rsurface.modeltvector3f_vertexbuffer = 0;
8585                         rsurface.modeltvector3f_bufferoffset = 0;
8586                         rsurface.modelnormal3f_vertexbuffer = 0;
8587                         rsurface.modelnormal3f_bufferoffset = 0;
8588                 }
8589                 else
8590                 {
8591                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8592                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8593                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8594                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8595                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8596                         rsurface.modelsvector3f = NULL;
8597                         rsurface.modeltvector3f = NULL;
8598                         rsurface.modelnormal3f = NULL;
8599                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8600                         rsurface.modelvertexmesh = NULL;
8601                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8602                         rsurface.modelvertexmesh_bufferoffset = 0;
8603                         rsurface.modelvertex3f_vertexbuffer = NULL;
8604                         rsurface.modelvertex3f_bufferoffset = 0;
8605                         rsurface.modelvertex3f_vertexbuffer = 0;
8606                         rsurface.modelvertex3f_bufferoffset = 0;
8607                         rsurface.modelsvector3f_vertexbuffer = 0;
8608                         rsurface.modelsvector3f_bufferoffset = 0;
8609                         rsurface.modeltvector3f_vertexbuffer = 0;
8610                         rsurface.modeltvector3f_bufferoffset = 0;
8611                         rsurface.modelnormal3f_vertexbuffer = 0;
8612                         rsurface.modelnormal3f_bufferoffset = 0;
8613                 }
8614                 rsurface.modelgeneratedvertex = true;
8615         }
8616         else
8617         {
8618                 if (rsurface.entityskeletaltransform3x4)
8619                 {
8620                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8621                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8622                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8623                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8624                 }
8625                 else
8626                 {
8627                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8628                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8629                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8630                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8631                 }
8632                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8633                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8634                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8635                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8636                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8637                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8638                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8639                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8640                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8641                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8642                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8643                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8644                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8645                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8646                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8647                 rsurface.modelgeneratedvertex = false;
8648         }
8649         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8650         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8651         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8652         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8653         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8654         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8655         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8656         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8657         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8658         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8659         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8660         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8661         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8662         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8663         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8664         rsurface.modelelement3i = model->surfmesh.data_element3i;
8665         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8666         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8667         rsurface.modelelement3s = model->surfmesh.data_element3s;
8668         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8669         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8670         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8671         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8672         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8673         rsurface.modelsurfaces = model->data_surfaces;
8674         rsurface.batchgeneratedvertex = false;
8675         rsurface.batchfirstvertex = 0;
8676         rsurface.batchnumvertices = 0;
8677         rsurface.batchfirsttriangle = 0;
8678         rsurface.batchnumtriangles = 0;
8679         rsurface.batchvertex3f  = NULL;
8680         rsurface.batchvertex3f_vertexbuffer = NULL;
8681         rsurface.batchvertex3f_bufferoffset = 0;
8682         rsurface.batchsvector3f = NULL;
8683         rsurface.batchsvector3f_vertexbuffer = NULL;
8684         rsurface.batchsvector3f_bufferoffset = 0;
8685         rsurface.batchtvector3f = NULL;
8686         rsurface.batchtvector3f_vertexbuffer = NULL;
8687         rsurface.batchtvector3f_bufferoffset = 0;
8688         rsurface.batchnormal3f  = NULL;
8689         rsurface.batchnormal3f_vertexbuffer = NULL;
8690         rsurface.batchnormal3f_bufferoffset = 0;
8691         rsurface.batchlightmapcolor4f = NULL;
8692         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8693         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8694         rsurface.batchtexcoordtexture2f = NULL;
8695         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8696         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8697         rsurface.batchtexcoordlightmap2f = NULL;
8698         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8699         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8700         rsurface.batchskeletalindex4ub = NULL;
8701         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8702         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8703         rsurface.batchskeletalweight4ub = NULL;
8704         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8705         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8706         rsurface.batchvertexmesh = NULL;
8707         rsurface.batchvertexmesh_vertexbuffer = NULL;
8708         rsurface.batchvertexmesh_bufferoffset = 0;
8709         rsurface.batchelement3i = NULL;
8710         rsurface.batchelement3i_indexbuffer = NULL;
8711         rsurface.batchelement3i_bufferoffset = 0;
8712         rsurface.batchelement3s = NULL;
8713         rsurface.batchelement3s_indexbuffer = NULL;
8714         rsurface.batchelement3s_bufferoffset = 0;
8715         rsurface.passcolor4f = NULL;
8716         rsurface.passcolor4f_vertexbuffer = NULL;
8717         rsurface.passcolor4f_bufferoffset = 0;
8718         rsurface.forcecurrenttextureupdate = false;
8719 }
8720
8721 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)
8722 {
8723         rsurface.entity = r_refdef.scene.worldentity;
8724         rsurface.skeleton = NULL;
8725         rsurface.ent_skinnum = 0;
8726         rsurface.ent_qwskin = -1;
8727         rsurface.ent_flags = entflags;
8728         rsurface.shadertime = r_refdef.scene.time - shadertime;
8729         rsurface.modelnumvertices = numvertices;
8730         rsurface.modelnumtriangles = numtriangles;
8731         rsurface.matrix = *matrix;
8732         rsurface.inversematrix = *inversematrix;
8733         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8734         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8735         R_EntityMatrix(&rsurface.matrix);
8736         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8737         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8738         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8739         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8740         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8741         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8742         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8743         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8744         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8745         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8746         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8747         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8748         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);
8749         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8750         rsurface.frameblend[0].lerp = 1;
8751         rsurface.ent_alttextures = false;
8752         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8753         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8754         rsurface.entityskeletaltransform3x4 = NULL;
8755         rsurface.entityskeletaltransform3x4buffer = NULL;
8756         rsurface.entityskeletaltransform3x4offset = 0;
8757         rsurface.entityskeletaltransform3x4size = 0;
8758         rsurface.entityskeletalnumtransforms = 0;
8759         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8760         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8761         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8762         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8763         if (wanttangents)
8764         {
8765                 rsurface.modelvertex3f = (float *)vertex3f;
8766                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8767                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8768                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8769         }
8770         else if (wantnormals)
8771         {
8772                 rsurface.modelvertex3f = (float *)vertex3f;
8773                 rsurface.modelsvector3f = NULL;
8774                 rsurface.modeltvector3f = NULL;
8775                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8776         }
8777         else
8778         {
8779                 rsurface.modelvertex3f = (float *)vertex3f;
8780                 rsurface.modelsvector3f = NULL;
8781                 rsurface.modeltvector3f = NULL;
8782                 rsurface.modelnormal3f = NULL;
8783         }
8784         rsurface.modelvertexmesh = NULL;
8785         rsurface.modelvertexmesh_vertexbuffer = NULL;
8786         rsurface.modelvertexmesh_bufferoffset = 0;
8787         rsurface.modelvertex3f_vertexbuffer = 0;
8788         rsurface.modelvertex3f_bufferoffset = 0;
8789         rsurface.modelsvector3f_vertexbuffer = 0;
8790         rsurface.modelsvector3f_bufferoffset = 0;
8791         rsurface.modeltvector3f_vertexbuffer = 0;
8792         rsurface.modeltvector3f_bufferoffset = 0;
8793         rsurface.modelnormal3f_vertexbuffer = 0;
8794         rsurface.modelnormal3f_bufferoffset = 0;
8795         rsurface.modelgeneratedvertex = true;
8796         rsurface.modellightmapcolor4f  = (float *)color4f;
8797         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8798         rsurface.modellightmapcolor4f_bufferoffset = 0;
8799         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8800         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8801         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8802         rsurface.modeltexcoordlightmap2f  = NULL;
8803         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8804         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8805         rsurface.modelskeletalindex4ub = NULL;
8806         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8807         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8808         rsurface.modelskeletalweight4ub = NULL;
8809         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8810         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8811         rsurface.modelelement3i = (int *)element3i;
8812         rsurface.modelelement3i_indexbuffer = NULL;
8813         rsurface.modelelement3i_bufferoffset = 0;
8814         rsurface.modelelement3s = (unsigned short *)element3s;
8815         rsurface.modelelement3s_indexbuffer = NULL;
8816         rsurface.modelelement3s_bufferoffset = 0;
8817         rsurface.modellightmapoffsets = NULL;
8818         rsurface.modelsurfaces = NULL;
8819         rsurface.batchgeneratedvertex = false;
8820         rsurface.batchfirstvertex = 0;
8821         rsurface.batchnumvertices = 0;
8822         rsurface.batchfirsttriangle = 0;
8823         rsurface.batchnumtriangles = 0;
8824         rsurface.batchvertex3f  = NULL;
8825         rsurface.batchvertex3f_vertexbuffer = NULL;
8826         rsurface.batchvertex3f_bufferoffset = 0;
8827         rsurface.batchsvector3f = NULL;
8828         rsurface.batchsvector3f_vertexbuffer = NULL;
8829         rsurface.batchsvector3f_bufferoffset = 0;
8830         rsurface.batchtvector3f = NULL;
8831         rsurface.batchtvector3f_vertexbuffer = NULL;
8832         rsurface.batchtvector3f_bufferoffset = 0;
8833         rsurface.batchnormal3f  = NULL;
8834         rsurface.batchnormal3f_vertexbuffer = NULL;
8835         rsurface.batchnormal3f_bufferoffset = 0;
8836         rsurface.batchlightmapcolor4f = NULL;
8837         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8838         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8839         rsurface.batchtexcoordtexture2f = NULL;
8840         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8841         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8842         rsurface.batchtexcoordlightmap2f = NULL;
8843         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8844         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8845         rsurface.batchskeletalindex4ub = NULL;
8846         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8847         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8848         rsurface.batchskeletalweight4ub = NULL;
8849         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8850         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8851         rsurface.batchvertexmesh = NULL;
8852         rsurface.batchvertexmesh_vertexbuffer = NULL;
8853         rsurface.batchvertexmesh_bufferoffset = 0;
8854         rsurface.batchelement3i = NULL;
8855         rsurface.batchelement3i_indexbuffer = NULL;
8856         rsurface.batchelement3i_bufferoffset = 0;
8857         rsurface.batchelement3s = NULL;
8858         rsurface.batchelement3s_indexbuffer = NULL;
8859         rsurface.batchelement3s_bufferoffset = 0;
8860         rsurface.passcolor4f = NULL;
8861         rsurface.passcolor4f_vertexbuffer = NULL;
8862         rsurface.passcolor4f_bufferoffset = 0;
8863         rsurface.forcecurrenttextureupdate = true;
8864
8865         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8866         {
8867                 if ((wantnormals || wanttangents) && !normal3f)
8868                 {
8869                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8870                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8871                 }
8872                 if (wanttangents && !svector3f)
8873                 {
8874                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8875                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8876                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8877                 }
8878         }
8879 }
8880
8881 float RSurf_FogPoint(const float *v)
8882 {
8883         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8884         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8885         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8886         float FogHeightFade = r_refdef.fogheightfade;
8887         float fogfrac;
8888         unsigned int fogmasktableindex;
8889         if (r_refdef.fogplaneviewabove)
8890                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8891         else
8892                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8893         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8894         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8895 }
8896
8897 float RSurf_FogVertex(const float *v)
8898 {
8899         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8900         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8901         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8902         float FogHeightFade = rsurface.fogheightfade;
8903         float fogfrac;
8904         unsigned int fogmasktableindex;
8905         if (r_refdef.fogplaneviewabove)
8906                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8907         else
8908                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8909         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8910         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8911 }
8912
8913 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8914 {
8915         int i;
8916         for (i = 0;i < numelements;i++)
8917                 outelement3i[i] = inelement3i[i] + adjust;
8918 }
8919
8920 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8921 extern cvar_t gl_vbo;
8922 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8923 {
8924         int deformindex;
8925         int firsttriangle;
8926         int numtriangles;
8927         int firstvertex;
8928         int endvertex;
8929         int numvertices;
8930         int surfacefirsttriangle;
8931         int surfacenumtriangles;
8932         int surfacefirstvertex;
8933         int surfaceendvertex;
8934         int surfacenumvertices;
8935         int batchnumsurfaces = texturenumsurfaces;
8936         int batchnumvertices;
8937         int batchnumtriangles;
8938         int needsupdate;
8939         int i, j;
8940         qboolean gaps;
8941         qboolean dynamicvertex;
8942         float amplitude;
8943         float animpos;
8944         float scale;
8945         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8946         float waveparms[4];
8947         unsigned char *ub;
8948         q3shaderinfo_deform_t *deform;
8949         const msurface_t *surface, *firstsurface;
8950         r_vertexmesh_t *vertexmesh;
8951         if (!texturenumsurfaces)
8952                 return;
8953         // find vertex range of this surface batch
8954         gaps = false;
8955         firstsurface = texturesurfacelist[0];
8956         firsttriangle = firstsurface->num_firsttriangle;
8957         batchnumvertices = 0;
8958         batchnumtriangles = 0;
8959         firstvertex = endvertex = firstsurface->num_firstvertex;
8960         for (i = 0;i < texturenumsurfaces;i++)
8961         {
8962                 surface = texturesurfacelist[i];
8963                 if (surface != firstsurface + i)
8964                         gaps = true;
8965                 surfacefirstvertex = surface->num_firstvertex;
8966                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8967                 surfacenumvertices = surface->num_vertices;
8968                 surfacenumtriangles = surface->num_triangles;
8969                 if (firstvertex > surfacefirstvertex)
8970                         firstvertex = surfacefirstvertex;
8971                 if (endvertex < surfaceendvertex)
8972                         endvertex = surfaceendvertex;
8973                 batchnumvertices += surfacenumvertices;
8974                 batchnumtriangles += surfacenumtriangles;
8975         }
8976
8977         r_refdef.stats[r_stat_batch_batches]++;
8978         if (gaps)
8979                 r_refdef.stats[r_stat_batch_withgaps]++;
8980         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8981         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8982         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8983
8984         // we now know the vertex range used, and if there are any gaps in it
8985         rsurface.batchfirstvertex = firstvertex;
8986         rsurface.batchnumvertices = endvertex - firstvertex;
8987         rsurface.batchfirsttriangle = firsttriangle;
8988         rsurface.batchnumtriangles = batchnumtriangles;
8989
8990         // this variable holds flags for which properties have been updated that
8991         // may require regenerating vertexmesh array...
8992         needsupdate = 0;
8993
8994         // check if any dynamic vertex processing must occur
8995         dynamicvertex = false;
8996
8997         // a cvar to force the dynamic vertex path to be taken, for debugging
8998         if (r_batch_debugdynamicvertexpath.integer)
8999         {
9000                 if (!dynamicvertex)
9001                 {
9002                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9003                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9004                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9005                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9006                 }
9007                 dynamicvertex = true;
9008         }
9009
9010         // if there is a chance of animated vertex colors, it's a dynamic batch
9011         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9012         {
9013                 if (!dynamicvertex)
9014                 {
9015                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9016                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9017                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9018                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9019                 }
9020                 dynamicvertex = true;
9021                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9022         }
9023
9024         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9025         {
9026                 switch (deform->deform)
9027                 {
9028                 default:
9029                 case Q3DEFORM_PROJECTIONSHADOW:
9030                 case Q3DEFORM_TEXT0:
9031                 case Q3DEFORM_TEXT1:
9032                 case Q3DEFORM_TEXT2:
9033                 case Q3DEFORM_TEXT3:
9034                 case Q3DEFORM_TEXT4:
9035                 case Q3DEFORM_TEXT5:
9036                 case Q3DEFORM_TEXT6:
9037                 case Q3DEFORM_TEXT7:
9038                 case Q3DEFORM_NONE:
9039                         break;
9040                 case Q3DEFORM_AUTOSPRITE:
9041                         if (!dynamicvertex)
9042                         {
9043                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9044                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9045                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9046                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9047                         }
9048                         dynamicvertex = true;
9049                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9050                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9051                         break;
9052                 case Q3DEFORM_AUTOSPRITE2:
9053                         if (!dynamicvertex)
9054                         {
9055                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9056                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9057                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9058                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9059                         }
9060                         dynamicvertex = true;
9061                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9062                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9063                         break;
9064                 case Q3DEFORM_NORMAL:
9065                         if (!dynamicvertex)
9066                         {
9067                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9068                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9069                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9070                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9071                         }
9072                         dynamicvertex = true;
9073                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9074                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9075                         break;
9076                 case Q3DEFORM_WAVE:
9077                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9078                                 break; // if wavefunc is a nop, ignore this transform
9079                         if (!dynamicvertex)
9080                         {
9081                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9082                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9083                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9084                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9085                         }
9086                         dynamicvertex = true;
9087                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9088                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9089                         break;
9090                 case Q3DEFORM_BULGE:
9091                         if (!dynamicvertex)
9092                         {
9093                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9094                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9095                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9096                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9097                         }
9098                         dynamicvertex = true;
9099                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9100                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9101                         break;
9102                 case Q3DEFORM_MOVE:
9103                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9104                                 break; // if wavefunc is a nop, ignore this transform
9105                         if (!dynamicvertex)
9106                         {
9107                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9108                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9109                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9110                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9111                         }
9112                         dynamicvertex = true;
9113                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9114                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9115                         break;
9116                 }
9117         }
9118         switch(rsurface.texture->tcgen.tcgen)
9119         {
9120         default:
9121         case Q3TCGEN_TEXTURE:
9122                 break;
9123         case Q3TCGEN_LIGHTMAP:
9124                 if (!dynamicvertex)
9125                 {
9126                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9127                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9128                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9129                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9130                 }
9131                 dynamicvertex = true;
9132                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9133                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9134                 break;
9135         case Q3TCGEN_VECTOR:
9136                 if (!dynamicvertex)
9137                 {
9138                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9139                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9140                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9141                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9142                 }
9143                 dynamicvertex = true;
9144                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9145                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9146                 break;
9147         case Q3TCGEN_ENVIRONMENT:
9148                 if (!dynamicvertex)
9149                 {
9150                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9151                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9152                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9153                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9154                 }
9155                 dynamicvertex = true;
9156                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9157                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9158                 break;
9159         }
9160         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9161         {
9162                 if (!dynamicvertex)
9163                 {
9164                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9165                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9166                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9167                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9168                 }
9169                 dynamicvertex = true;
9170                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9171                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9172         }
9173
9174         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9175         {
9176                 if (!dynamicvertex)
9177                 {
9178                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9179                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9180                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9181                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9182                 }
9183                 dynamicvertex = true;
9184                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9185         }
9186
9187         // when the model data has no vertex buffer (dynamic mesh), we need to
9188         // eliminate gaps
9189         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9190                 batchneed |= BATCHNEED_NOGAPS;
9191
9192         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9193         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9194         // we ensure this by treating the vertex batch as dynamic...
9195         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9196         {
9197                 if (!dynamicvertex)
9198                 {
9199                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9200                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9201                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9202                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9203                 }
9204                 dynamicvertex = true;
9205         }
9206
9207         if (dynamicvertex)
9208         {
9209                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9210                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9211                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9212                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9213                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9214                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9215                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9216                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9217         }
9218
9219         // if needsupdate, we have to do a dynamic vertex batch for sure
9220         if (needsupdate & batchneed)
9221         {
9222                 if (!dynamicvertex)
9223                 {
9224                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9225                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9226                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9227                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9228                 }
9229                 dynamicvertex = true;
9230         }
9231
9232         // see if we need to build vertexmesh from arrays
9233         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9234         {
9235                 if (!dynamicvertex)
9236                 {
9237                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9238                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9239                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9240                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9241                 }
9242                 dynamicvertex = true;
9243         }
9244
9245         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9246         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9247                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9248
9249         rsurface.batchvertex3f = rsurface.modelvertex3f;
9250         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9251         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9252         rsurface.batchsvector3f = rsurface.modelsvector3f;
9253         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9254         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9255         rsurface.batchtvector3f = rsurface.modeltvector3f;
9256         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9257         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9258         rsurface.batchnormal3f = rsurface.modelnormal3f;
9259         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9260         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9261         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9262         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9263         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9264         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9265         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9266         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9267         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9268         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9269         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9270         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9271         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9272         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9273         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9274         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9275         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9276         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9277         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9278         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9279         rsurface.batchelement3i = rsurface.modelelement3i;
9280         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9281         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9282         rsurface.batchelement3s = rsurface.modelelement3s;
9283         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9284         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9285         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9286         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9287         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9288         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9289         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9290
9291         // if any dynamic vertex processing has to occur in software, we copy the
9292         // entire surface list together before processing to rebase the vertices
9293         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9294         //
9295         // if any gaps exist and we do not have a static vertex buffer, we have to
9296         // copy the surface list together to avoid wasting upload bandwidth on the
9297         // vertices in the gaps.
9298         //
9299         // if gaps exist and we have a static vertex buffer, we can choose whether
9300         // to combine the index buffer ranges into one dynamic index buffer or
9301         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9302         //
9303         // in many cases the batch is reduced to one draw call.
9304
9305         rsurface.batchmultidraw = false;
9306         rsurface.batchmultidrawnumsurfaces = 0;
9307         rsurface.batchmultidrawsurfacelist = NULL;
9308
9309         if (!dynamicvertex)
9310         {
9311                 // static vertex data, just set pointers...
9312                 rsurface.batchgeneratedvertex = false;
9313                 // if there are gaps, we want to build a combined index buffer,
9314                 // otherwise use the original static buffer with an appropriate offset
9315                 if (gaps)
9316                 {
9317                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9318                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9319                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9320                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9321                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9322                         {
9323                                 rsurface.batchmultidraw = true;
9324                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9325                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9326                                 return;
9327                         }
9328                         // build a new triangle elements array for this batch
9329                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9330                         rsurface.batchfirsttriangle = 0;
9331                         numtriangles = 0;
9332                         for (i = 0;i < texturenumsurfaces;i++)
9333                         {
9334                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9335                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9336                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9337                                 numtriangles += surfacenumtriangles;
9338                         }
9339                         rsurface.batchelement3i_indexbuffer = NULL;
9340                         rsurface.batchelement3i_bufferoffset = 0;
9341                         rsurface.batchelement3s = NULL;
9342                         rsurface.batchelement3s_indexbuffer = NULL;
9343                         rsurface.batchelement3s_bufferoffset = 0;
9344                         if (endvertex <= 65536)
9345                         {
9346                                 // make a 16bit (unsigned short) index array if possible
9347                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9348                                 for (i = 0;i < numtriangles*3;i++)
9349                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9350                         }
9351                         // upload buffer data for the copytriangles batch
9352                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9353                         {
9354                                 if (rsurface.batchelement3s)
9355                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9356                                 else if (rsurface.batchelement3i)
9357                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9358                         }
9359                 }
9360                 else
9361                 {
9362                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9363                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9364                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9365                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9366                 }
9367                 return;
9368         }
9369
9370         // something needs software processing, do it for real...
9371         // we only directly handle separate array data in this case and then
9372         // generate interleaved data if needed...
9373         rsurface.batchgeneratedvertex = true;
9374         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9375         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9376         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9377         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9378
9379         // now copy the vertex data into a combined array and make an index array
9380         // (this is what Quake3 does all the time)
9381         // we also apply any skeletal animation here that would have been done in
9382         // the vertex shader, because most of the dynamic vertex animation cases
9383         // need actual vertex positions and normals
9384         //if (dynamicvertex)
9385         {
9386                 rsurface.batchvertexmesh = NULL;
9387                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9388                 rsurface.batchvertexmesh_bufferoffset = 0;
9389                 rsurface.batchvertex3f = NULL;
9390                 rsurface.batchvertex3f_vertexbuffer = NULL;
9391                 rsurface.batchvertex3f_bufferoffset = 0;
9392                 rsurface.batchsvector3f = NULL;
9393                 rsurface.batchsvector3f_vertexbuffer = NULL;
9394                 rsurface.batchsvector3f_bufferoffset = 0;
9395                 rsurface.batchtvector3f = NULL;
9396                 rsurface.batchtvector3f_vertexbuffer = NULL;
9397                 rsurface.batchtvector3f_bufferoffset = 0;
9398                 rsurface.batchnormal3f = NULL;
9399                 rsurface.batchnormal3f_vertexbuffer = NULL;
9400                 rsurface.batchnormal3f_bufferoffset = 0;
9401                 rsurface.batchlightmapcolor4f = NULL;
9402                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9403                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9404                 rsurface.batchtexcoordtexture2f = NULL;
9405                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9406                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9407                 rsurface.batchtexcoordlightmap2f = NULL;
9408                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9409                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9410                 rsurface.batchskeletalindex4ub = NULL;
9411                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9412                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9413                 rsurface.batchskeletalweight4ub = NULL;
9414                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9415                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9416                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9417                 rsurface.batchelement3i_indexbuffer = NULL;
9418                 rsurface.batchelement3i_bufferoffset = 0;
9419                 rsurface.batchelement3s = NULL;
9420                 rsurface.batchelement3s_indexbuffer = NULL;
9421                 rsurface.batchelement3s_bufferoffset = 0;
9422                 rsurface.batchskeletaltransform3x4buffer = NULL;
9423                 rsurface.batchskeletaltransform3x4offset = 0;
9424                 rsurface.batchskeletaltransform3x4size = 0;
9425                 // we'll only be setting up certain arrays as needed
9426                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9427                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9428                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9429                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9430                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9431                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9432                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9433                 {
9434                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9435                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9436                 }
9437                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9438                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9439                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9440                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9441                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9442                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9443                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9444                 {
9445                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9446                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9447                 }
9448                 numvertices = 0;
9449                 numtriangles = 0;
9450                 for (i = 0;i < texturenumsurfaces;i++)
9451                 {
9452                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9453                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9454                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9455                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9456                         // copy only the data requested
9457                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9458                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9459                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9460                         {
9461                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9462                                 {
9463                                         if (rsurface.batchvertex3f)
9464                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9465                                         else
9466                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9467                                 }
9468                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9469                                 {
9470                                         if (rsurface.modelnormal3f)
9471                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9472                                         else
9473                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9474                                 }
9475                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9476                                 {
9477                                         if (rsurface.modelsvector3f)
9478                                         {
9479                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9480                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9481                                         }
9482                                         else
9483                                         {
9484                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9485                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9486                                         }
9487                                 }
9488                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9489                                 {
9490                                         if (rsurface.modellightmapcolor4f)
9491                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9492                                         else
9493                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9494                                 }
9495                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9496                                 {
9497                                         if (rsurface.modeltexcoordtexture2f)
9498                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9499                                         else
9500                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9501                                 }
9502                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9503                                 {
9504                                         if (rsurface.modeltexcoordlightmap2f)
9505                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9506                                         else
9507                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9508                                 }
9509                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9510                                 {
9511                                         if (rsurface.modelskeletalindex4ub)
9512                                         {
9513                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9514                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9515                                         }
9516                                         else
9517                                         {
9518                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9519                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9520                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9521                                                 for (j = 0;j < surfacenumvertices;j++)
9522                                                         ub[j*4] = 255;
9523                                         }
9524                                 }
9525                         }
9526                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9527                         numvertices += surfacenumvertices;
9528                         numtriangles += surfacenumtriangles;
9529                 }
9530
9531                 // generate a 16bit index array as well if possible
9532                 // (in general, dynamic batches fit)
9533                 if (numvertices <= 65536)
9534                 {
9535                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9536                         for (i = 0;i < numtriangles*3;i++)
9537                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9538                 }
9539
9540                 // since we've copied everything, the batch now starts at 0
9541                 rsurface.batchfirstvertex = 0;
9542                 rsurface.batchnumvertices = batchnumvertices;
9543                 rsurface.batchfirsttriangle = 0;
9544                 rsurface.batchnumtriangles = batchnumtriangles;
9545         }
9546
9547         // apply skeletal animation that would have been done in the vertex shader
9548         if (rsurface.batchskeletaltransform3x4)
9549         {
9550                 const unsigned char *si;
9551                 const unsigned char *sw;
9552                 const float *t[4];
9553                 const float *b = rsurface.batchskeletaltransform3x4;
9554                 float *vp, *vs, *vt, *vn;
9555                 float w[4];
9556                 float m[3][4], n[3][4];
9557                 float tp[3], ts[3], tt[3], tn[3];
9558                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9559                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9560                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9561                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9562                 si = rsurface.batchskeletalindex4ub;
9563                 sw = rsurface.batchskeletalweight4ub;
9564                 vp = rsurface.batchvertex3f;
9565                 vs = rsurface.batchsvector3f;
9566                 vt = rsurface.batchtvector3f;
9567                 vn = rsurface.batchnormal3f;
9568                 memset(m[0], 0, sizeof(m));
9569                 memset(n[0], 0, sizeof(n));
9570                 for (i = 0;i < batchnumvertices;i++)
9571                 {
9572                         t[0] = b + si[0]*12;
9573                         if (sw[0] == 255)
9574                         {
9575                                 // common case - only one matrix
9576                                 m[0][0] = t[0][ 0];
9577                                 m[0][1] = t[0][ 1];
9578                                 m[0][2] = t[0][ 2];
9579                                 m[0][3] = t[0][ 3];
9580                                 m[1][0] = t[0][ 4];
9581                                 m[1][1] = t[0][ 5];
9582                                 m[1][2] = t[0][ 6];
9583                                 m[1][3] = t[0][ 7];
9584                                 m[2][0] = t[0][ 8];
9585                                 m[2][1] = t[0][ 9];
9586                                 m[2][2] = t[0][10];
9587                                 m[2][3] = t[0][11];
9588                         }
9589                         else if (sw[2] + sw[3])
9590                         {
9591                                 // blend 4 matrices
9592                                 t[1] = b + si[1]*12;
9593                                 t[2] = b + si[2]*12;
9594                                 t[3] = b + si[3]*12;
9595                                 w[0] = sw[0] * (1.0f / 255.0f);
9596                                 w[1] = sw[1] * (1.0f / 255.0f);
9597                                 w[2] = sw[2] * (1.0f / 255.0f);
9598                                 w[3] = sw[3] * (1.0f / 255.0f);
9599                                 // blend the matrices
9600                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9601                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9602                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9603                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9604                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9605                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9606                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9607                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9608                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9609                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9610                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9611                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9612                         }
9613                         else
9614                         {
9615                                 // blend 2 matrices
9616                                 t[1] = b + si[1]*12;
9617                                 w[0] = sw[0] * (1.0f / 255.0f);
9618                                 w[1] = sw[1] * (1.0f / 255.0f);
9619                                 // blend the matrices
9620                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9621                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9622                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9623                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9624                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9625                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9626                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9627                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9628                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9629                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9630                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9631                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9632                         }
9633                         si += 4;
9634                         sw += 4;
9635                         // modify the vertex
9636                         VectorCopy(vp, tp);
9637                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9638                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9639                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9640                         vp += 3;
9641                         if (vn)
9642                         {
9643                                 // the normal transformation matrix is a set of cross products...
9644                                 CrossProduct(m[1], m[2], n[0]);
9645                                 CrossProduct(m[2], m[0], n[1]);
9646                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9647                                 VectorCopy(vn, tn);
9648                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9649                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9650                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9651                                 VectorNormalize(vn);
9652                                 vn += 3;
9653                                 if (vs)
9654                                 {
9655                                         VectorCopy(vs, ts);
9656                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9657                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9658                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9659                                         VectorNormalize(vs);
9660                                         vs += 3;
9661                                         VectorCopy(vt, tt);
9662                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9663                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9664                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9665                                         VectorNormalize(vt);
9666                                         vt += 3;
9667                                 }
9668                         }
9669                 }
9670                 rsurface.batchskeletaltransform3x4 = NULL;
9671                 rsurface.batchskeletalnumtransforms = 0;
9672         }
9673
9674         // q1bsp surfaces rendered in vertex color mode have to have colors
9675         // calculated based on lightstyles
9676         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9677         {
9678                 // generate color arrays for the surfaces in this list
9679                 int c[4];
9680                 int scale;
9681                 int size3;
9682                 const int *offsets;
9683                 const unsigned char *lm;
9684                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9685                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9686                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9687                 numvertices = 0;
9688                 for (i = 0;i < texturenumsurfaces;i++)
9689                 {
9690                         surface = texturesurfacelist[i];
9691                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9692                         surfacenumvertices = surface->num_vertices;
9693                         if (surface->lightmapinfo->samples)
9694                         {
9695                                 for (j = 0;j < surfacenumvertices;j++)
9696                                 {
9697                                         lm = surface->lightmapinfo->samples + offsets[j];
9698                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9699                                         VectorScale(lm, scale, c);
9700                                         if (surface->lightmapinfo->styles[1] != 255)
9701                                         {
9702                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9703                                                 lm += size3;
9704                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9705                                                 VectorMA(c, scale, lm, c);
9706                                                 if (surface->lightmapinfo->styles[2] != 255)
9707                                                 {
9708                                                         lm += size3;
9709                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9710                                                         VectorMA(c, scale, lm, c);
9711                                                         if (surface->lightmapinfo->styles[3] != 255)
9712                                                         {
9713                                                                 lm += size3;
9714                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9715                                                                 VectorMA(c, scale, lm, c);
9716                                                         }
9717                                                 }
9718                                         }
9719                                         c[0] >>= 7;
9720                                         c[1] >>= 7;
9721                                         c[2] >>= 7;
9722                                         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);
9723                                         numvertices++;
9724                                 }
9725                         }
9726                         else
9727                         {
9728                                 for (j = 0;j < surfacenumvertices;j++)
9729                                 {
9730                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9731                                         numvertices++;
9732                                 }
9733                         }
9734                 }
9735         }
9736
9737         // if vertices are deformed (sprite flares and things in maps, possibly
9738         // water waves, bulges and other deformations), modify the copied vertices
9739         // in place
9740         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9741         {
9742                 switch (deform->deform)
9743                 {
9744                 default:
9745                 case Q3DEFORM_PROJECTIONSHADOW:
9746                 case Q3DEFORM_TEXT0:
9747                 case Q3DEFORM_TEXT1:
9748                 case Q3DEFORM_TEXT2:
9749                 case Q3DEFORM_TEXT3:
9750                 case Q3DEFORM_TEXT4:
9751                 case Q3DEFORM_TEXT5:
9752                 case Q3DEFORM_TEXT6:
9753                 case Q3DEFORM_TEXT7:
9754                 case Q3DEFORM_NONE:
9755                         break;
9756                 case Q3DEFORM_AUTOSPRITE:
9757                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9758                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9759                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9760                         VectorNormalize(newforward);
9761                         VectorNormalize(newright);
9762                         VectorNormalize(newup);
9763 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9764 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9765 //                      rsurface.batchvertex3f_bufferoffset = 0;
9766 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9767 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9768 //                      rsurface.batchsvector3f_bufferoffset = 0;
9769 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9770 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9771 //                      rsurface.batchtvector3f_bufferoffset = 0;
9772 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9773 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9774 //                      rsurface.batchnormal3f_bufferoffset = 0;
9775                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9776                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9777                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9778                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9779                                 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);
9780                         // a single autosprite surface can contain multiple sprites...
9781                         for (j = 0;j < batchnumvertices - 3;j += 4)
9782                         {
9783                                 VectorClear(center);
9784                                 for (i = 0;i < 4;i++)
9785                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9786                                 VectorScale(center, 0.25f, center);
9787                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9788                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9789                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9790                                 for (i = 0;i < 4;i++)
9791                                 {
9792                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9793                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9794                                 }
9795                         }
9796                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9797                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9798                         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);
9799                         break;
9800                 case Q3DEFORM_AUTOSPRITE2:
9801                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9802                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9803                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9804                         VectorNormalize(newforward);
9805                         VectorNormalize(newright);
9806                         VectorNormalize(newup);
9807 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9808 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9809 //                      rsurface.batchvertex3f_bufferoffset = 0;
9810                         {
9811                                 const float *v1, *v2;
9812                                 vec3_t start, end;
9813                                 float f, l;
9814                                 struct
9815                                 {
9816                                         float length2;
9817                                         const float *v1;
9818                                         const float *v2;
9819                                 }
9820                                 shortest[2];
9821                                 memset(shortest, 0, sizeof(shortest));
9822                                 // a single autosprite surface can contain multiple sprites...
9823                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9824                                 {
9825                                         VectorClear(center);
9826                                         for (i = 0;i < 4;i++)
9827                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9828                                         VectorScale(center, 0.25f, center);
9829                                         // find the two shortest edges, then use them to define the
9830                                         // axis vectors for rotating around the central axis
9831                                         for (i = 0;i < 6;i++)
9832                                         {
9833                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9834                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9835                                                 l = VectorDistance2(v1, v2);
9836                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9837                                                 if (v1[2] != v2[2])
9838                                                         l += (1.0f / 1024.0f);
9839                                                 if (shortest[0].length2 > l || i == 0)
9840                                                 {
9841                                                         shortest[1] = shortest[0];
9842                                                         shortest[0].length2 = l;
9843                                                         shortest[0].v1 = v1;
9844                                                         shortest[0].v2 = v2;
9845                                                 }
9846                                                 else if (shortest[1].length2 > l || i == 1)
9847                                                 {
9848                                                         shortest[1].length2 = l;
9849                                                         shortest[1].v1 = v1;
9850                                                         shortest[1].v2 = v2;
9851                                                 }
9852                                         }
9853                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9854                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9855                                         // this calculates the right vector from the shortest edge
9856                                         // and the up vector from the edge midpoints
9857                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9858                                         VectorNormalize(right);
9859                                         VectorSubtract(end, start, up);
9860                                         VectorNormalize(up);
9861                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9862                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9863                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9864                                         VectorNegate(forward, forward);
9865                                         VectorReflect(forward, 0, up, forward);
9866                                         VectorNormalize(forward);
9867                                         CrossProduct(up, forward, newright);
9868                                         VectorNormalize(newright);
9869                                         // rotate the quad around the up axis vector, this is made
9870                                         // especially easy by the fact we know the quad is flat,
9871                                         // so we only have to subtract the center position and
9872                                         // measure distance along the right vector, and then
9873                                         // multiply that by the newright vector and add back the
9874                                         // center position
9875                                         // we also need to subtract the old position to undo the
9876                                         // displacement from the center, which we do with a
9877                                         // DotProduct, the subtraction/addition of center is also
9878                                         // optimized into DotProducts here
9879                                         l = DotProduct(right, center);
9880                                         for (i = 0;i < 4;i++)
9881                                         {
9882                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9883                                                 f = DotProduct(right, v1) - l;
9884                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9885                                         }
9886                                 }
9887                         }
9888                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9889                         {
9890 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9891 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9892 //                              rsurface.batchnormal3f_bufferoffset = 0;
9893                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9894                         }
9895                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9896                         {
9897 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9898 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9899 //                              rsurface.batchsvector3f_bufferoffset = 0;
9900 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9901 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9902 //                              rsurface.batchtvector3f_bufferoffset = 0;
9903                                 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);
9904                         }
9905                         break;
9906                 case Q3DEFORM_NORMAL:
9907                         // deform the normals to make reflections wavey
9908                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9909                         rsurface.batchnormal3f_vertexbuffer = NULL;
9910                         rsurface.batchnormal3f_bufferoffset = 0;
9911                         for (j = 0;j < batchnumvertices;j++)
9912                         {
9913                                 float vertex[3];
9914                                 float *normal = rsurface.batchnormal3f + 3*j;
9915                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9916                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9917                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9918                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9919                                 VectorNormalize(normal);
9920                         }
9921                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9922                         {
9923 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9924 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9925 //                              rsurface.batchsvector3f_bufferoffset = 0;
9926 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9927 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9928 //                              rsurface.batchtvector3f_bufferoffset = 0;
9929                                 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);
9930                         }
9931                         break;
9932                 case Q3DEFORM_WAVE:
9933                         // deform vertex array to make wavey water and flags and such
9934                         waveparms[0] = deform->waveparms[0];
9935                         waveparms[1] = deform->waveparms[1];
9936                         waveparms[2] = deform->waveparms[2];
9937                         waveparms[3] = deform->waveparms[3];
9938                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9939                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9940                         // this is how a divisor of vertex influence on deformation
9941                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9942                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9943 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9944 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9945 //                      rsurface.batchvertex3f_bufferoffset = 0;
9946 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9947 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9948 //                      rsurface.batchnormal3f_bufferoffset = 0;
9949                         for (j = 0;j < batchnumvertices;j++)
9950                         {
9951                                 // if the wavefunc depends on time, evaluate it per-vertex
9952                                 if (waveparms[3])
9953                                 {
9954                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9955                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9956                                 }
9957                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9958                         }
9959                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9960                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9961                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9962                         {
9963 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9964 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9965 //                              rsurface.batchsvector3f_bufferoffset = 0;
9966 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9967 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9968 //                              rsurface.batchtvector3f_bufferoffset = 0;
9969                                 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);
9970                         }
9971                         break;
9972                 case Q3DEFORM_BULGE:
9973                         // deform vertex array to make the surface have moving bulges
9974 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9975 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9976 //                      rsurface.batchvertex3f_bufferoffset = 0;
9977 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9978 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9979 //                      rsurface.batchnormal3f_bufferoffset = 0;
9980                         for (j = 0;j < batchnumvertices;j++)
9981                         {
9982                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9983                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9984                         }
9985                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9986                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9987                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9988                         {
9989 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9990 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9991 //                              rsurface.batchsvector3f_bufferoffset = 0;
9992 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9993 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9994 //                              rsurface.batchtvector3f_bufferoffset = 0;
9995                                 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);
9996                         }
9997                         break;
9998                 case Q3DEFORM_MOVE:
9999                         // deform vertex array
10000                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10001                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10002                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10003                         VectorScale(deform->parms, scale, waveparms);
10004 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10005 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10006 //                      rsurface.batchvertex3f_bufferoffset = 0;
10007                         for (j = 0;j < batchnumvertices;j++)
10008                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10009                         break;
10010                 }
10011         }
10012
10013         // generate texcoords based on the chosen texcoord source
10014         switch(rsurface.texture->tcgen.tcgen)
10015         {
10016         default:
10017         case Q3TCGEN_TEXTURE:
10018                 break;
10019         case Q3TCGEN_LIGHTMAP:
10020 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10021 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10022 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10023                 if (rsurface.batchtexcoordlightmap2f)
10024                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
10025                 break;
10026         case Q3TCGEN_VECTOR:
10027 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10028 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10029 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10030                 for (j = 0;j < batchnumvertices;j++)
10031                 {
10032                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10033                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10034                 }
10035                 break;
10036         case Q3TCGEN_ENVIRONMENT:
10037                 // make environment reflections using a spheremap
10038                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10039                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10040                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10041                 for (j = 0;j < batchnumvertices;j++)
10042                 {
10043                         // identical to Q3A's method, but executed in worldspace so
10044                         // carried models can be shiny too
10045
10046                         float viewer[3], d, reflected[3], worldreflected[3];
10047
10048                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10049                         // VectorNormalize(viewer);
10050
10051                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10052
10053                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10054                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10055                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10056                         // note: this is proportinal to viewer, so we can normalize later
10057
10058                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10059                         VectorNormalize(worldreflected);
10060
10061                         // note: this sphere map only uses world x and z!
10062                         // so positive and negative y will LOOK THE SAME.
10063                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10064                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10065                 }
10066                 break;
10067         }
10068         // the only tcmod that needs software vertex processing is turbulent, so
10069         // check for it here and apply the changes if needed
10070         // and we only support that as the first one
10071         // (handling a mixture of turbulent and other tcmods would be problematic
10072         //  without punting it entirely to a software path)
10073         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10074         {
10075                 amplitude = rsurface.texture->tcmods[0].parms[1];
10076                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10077 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10078 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10079 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10080                 for (j = 0;j < batchnumvertices;j++)
10081                 {
10082                         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);
10083                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10084                 }
10085         }
10086
10087         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10088         {
10089                 // convert the modified arrays to vertex structs
10090 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10091 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10092 //              rsurface.batchvertexmesh_bufferoffset = 0;
10093                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10094                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10095                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10096                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10097                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10098                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10099                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10100                 {
10101                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10102                         {
10103                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10104                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10105                         }
10106                 }
10107                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10108                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10109                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10110                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10111                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10112                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10113                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10114                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10115                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10116                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10117                 {
10118                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10119                         {
10120                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10121                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10122                         }
10123                 }
10124         }
10125
10126         // upload buffer data for the dynamic batch
10127         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10128         {
10129                 if (rsurface.batchvertexmesh)
10130                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10131                 else
10132                 {
10133                         if (rsurface.batchvertex3f)
10134                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10135                         if (rsurface.batchsvector3f)
10136                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10137                         if (rsurface.batchtvector3f)
10138                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10139                         if (rsurface.batchnormal3f)
10140                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10141                         if (rsurface.batchlightmapcolor4f)
10142                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10143                         if (rsurface.batchtexcoordtexture2f)
10144                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10145                         if (rsurface.batchtexcoordlightmap2f)
10146                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10147                         if (rsurface.batchskeletalindex4ub)
10148                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10149                         if (rsurface.batchskeletalweight4ub)
10150                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10151                 }
10152                 if (rsurface.batchelement3s)
10153                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10154                 else if (rsurface.batchelement3i)
10155                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10156         }
10157 }
10158
10159 void RSurf_DrawBatch(void)
10160 {
10161         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10162         // through the pipeline, killing it earlier in the pipeline would have
10163         // per-surface overhead rather than per-batch overhead, so it's best to
10164         // reject it here, before it hits glDraw.
10165         if (rsurface.batchnumtriangles == 0)
10166                 return;
10167 #if 0
10168         // batch debugging code
10169         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10170         {
10171                 int i;
10172                 int j;
10173                 int c;
10174                 const int *e;
10175                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10176                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10177                 {
10178                         c = e[i];
10179                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10180                         {
10181                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10182                                 {
10183                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10184                                                 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);
10185                                         break;
10186                                 }
10187                         }
10188                 }
10189         }
10190 #endif
10191         if (rsurface.batchmultidraw)
10192         {
10193                 // issue multiple draws rather than copying index data
10194                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10195                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10196                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10197                 for (i = 0;i < numsurfaces;)
10198                 {
10199                         // combine consecutive surfaces as one draw
10200                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10201                                 if (surfacelist[j] != surfacelist[k] + 1)
10202                                         break;
10203                         firstvertex = surfacelist[i]->num_firstvertex;
10204                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10205                         firsttriangle = surfacelist[i]->num_firsttriangle;
10206                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10207                         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);
10208                         i = j;
10209                 }
10210         }
10211         else
10212         {
10213                 // there is only one consecutive run of index data (may have been combined)
10214                 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);
10215         }
10216 }
10217
10218 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10219 {
10220         // pick the closest matching water plane
10221         int planeindex, vertexindex, bestplaneindex = -1;
10222         float d, bestd;
10223         vec3_t vert;
10224         const float *v;
10225         r_waterstate_waterplane_t *p;
10226         qboolean prepared = false;
10227         bestd = 0;
10228         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10229         {
10230                 if(p->camera_entity != rsurface.texture->camera_entity)
10231                         continue;
10232                 d = 0;
10233                 if(!prepared)
10234                 {
10235                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10236                         prepared = true;
10237                         if(rsurface.batchnumvertices == 0)
10238                                 break;
10239                 }
10240                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10241                 {
10242                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10243                         d += fabs(PlaneDiff(vert, &p->plane));
10244                 }
10245                 if (bestd > d || bestplaneindex < 0)
10246                 {
10247                         bestd = d;
10248                         bestplaneindex = planeindex;
10249                 }
10250         }
10251         return bestplaneindex;
10252         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10253         // this situation though, as it might be better to render single larger
10254         // batches with useless stuff (backface culled for example) than to
10255         // render multiple smaller batches
10256 }
10257
10258 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10259 {
10260         int i;
10261         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10262         rsurface.passcolor4f_vertexbuffer = 0;
10263         rsurface.passcolor4f_bufferoffset = 0;
10264         for (i = 0;i < rsurface.batchnumvertices;i++)
10265                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10266 }
10267
10268 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10269 {
10270         int i;
10271         float f;
10272         const float *v;
10273         const float *c;
10274         float *c2;
10275         if (rsurface.passcolor4f)
10276         {
10277                 // generate color arrays
10278                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10279                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10280                 rsurface.passcolor4f_vertexbuffer = 0;
10281                 rsurface.passcolor4f_bufferoffset = 0;
10282                 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)
10283                 {
10284                         f = RSurf_FogVertex(v);
10285                         c2[0] = c[0] * f;
10286                         c2[1] = c[1] * f;
10287                         c2[2] = c[2] * f;
10288                         c2[3] = c[3];
10289                 }
10290         }
10291         else
10292         {
10293                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10294                 rsurface.passcolor4f_vertexbuffer = 0;
10295                 rsurface.passcolor4f_bufferoffset = 0;
10296                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10297                 {
10298                         f = RSurf_FogVertex(v);
10299                         c2[0] = f;
10300                         c2[1] = f;
10301                         c2[2] = f;
10302                         c2[3] = 1;
10303                 }
10304         }
10305 }
10306
10307 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10308 {
10309         int i;
10310         float f;
10311         const float *v;
10312         const float *c;
10313         float *c2;
10314         if (!rsurface.passcolor4f)
10315                 return;
10316         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10317         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10318         rsurface.passcolor4f_vertexbuffer = 0;
10319         rsurface.passcolor4f_bufferoffset = 0;
10320         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)
10321         {
10322                 f = RSurf_FogVertex(v);
10323                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10324                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10325                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10326                 c2[3] = c[3];
10327         }
10328 }
10329
10330 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10331 {
10332         int i;
10333         const float *c;
10334         float *c2;
10335         if (!rsurface.passcolor4f)
10336                 return;
10337         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10338         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10339         rsurface.passcolor4f_vertexbuffer = 0;
10340         rsurface.passcolor4f_bufferoffset = 0;
10341         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10342         {
10343                 c2[0] = c[0] * r;
10344                 c2[1] = c[1] * g;
10345                 c2[2] = c[2] * b;
10346                 c2[3] = c[3] * a;
10347         }
10348 }
10349
10350 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10351 {
10352         int i;
10353         const float *c;
10354         float *c2;
10355         if (!rsurface.passcolor4f)
10356                 return;
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, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10362         {
10363                 c2[0] = c[0] + r_refdef.scene.ambient;
10364                 c2[1] = c[1] + r_refdef.scene.ambient;
10365                 c2[2] = c[2] + r_refdef.scene.ambient;
10366                 c2[3] = c[3];
10367         }
10368 }
10369
10370 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10371 {
10372         // TODO: optimize
10373         rsurface.passcolor4f = NULL;
10374         rsurface.passcolor4f_vertexbuffer = 0;
10375         rsurface.passcolor4f_bufferoffset = 0;
10376         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10377         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10378         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10379         GL_Color(r, g, b, a);
10380         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10381         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10382         R_Mesh_TexMatrix(0, NULL);
10383         RSurf_DrawBatch();
10384 }
10385
10386 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10387 {
10388         // TODO: optimize applyfog && applycolor case
10389         // just apply fog if necessary, and tint the fog color array if necessary
10390         rsurface.passcolor4f = NULL;
10391         rsurface.passcolor4f_vertexbuffer = 0;
10392         rsurface.passcolor4f_bufferoffset = 0;
10393         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10394         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10395         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10396         GL_Color(r, g, b, a);
10397         RSurf_DrawBatch();
10398 }
10399
10400 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10401 {
10402         // TODO: optimize
10403         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10404         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10405         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10406         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10407         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10408         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10409         GL_Color(r, g, b, a);
10410         RSurf_DrawBatch();
10411 }
10412
10413 static void RSurf_DrawBatch_GL11_ClampColor(void)
10414 {
10415         int i;
10416         const float *c1;
10417         float *c2;
10418         if (!rsurface.passcolor4f)
10419                 return;
10420         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10421         {
10422                 c2[0] = bound(0.0f, c1[0], 1.0f);
10423                 c2[1] = bound(0.0f, c1[1], 1.0f);
10424                 c2[2] = bound(0.0f, c1[2], 1.0f);
10425                 c2[3] = bound(0.0f, c1[3], 1.0f);
10426         }
10427 }
10428
10429 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10430 {
10431         int i;
10432         float f;
10433         const float *v;
10434         const float *n;
10435         float *c;
10436         //vec3_t eyedir;
10437
10438         // fake shading
10439         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10440         rsurface.passcolor4f_vertexbuffer = 0;
10441         rsurface.passcolor4f_bufferoffset = 0;
10442         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)
10443         {
10444                 f = -DotProduct(r_refdef.view.forward, n);
10445                 f = max(0, f);
10446                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10447                 f *= r_refdef.lightmapintensity;
10448                 Vector4Set(c, f, f, f, 1);
10449         }
10450 }
10451
10452 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10453 {
10454         RSurf_DrawBatch_GL11_ApplyFakeLight();
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         RSurf_DrawBatch();
10460 }
10461
10462 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10463 {
10464         int i;
10465         float f;
10466         float alpha;
10467         const float *v;
10468         const float *n;
10469         float *c;
10470         vec3_t ambientcolor;
10471         vec3_t diffusecolor;
10472         vec3_t lightdir;
10473         // TODO: optimize
10474         // model lighting
10475         VectorCopy(rsurface.modellight_lightdir, lightdir);
10476         f = 0.5f * r_refdef.lightmapintensity;
10477         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10478         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10479         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10480         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10481         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10482         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10483         alpha = *a;
10484         if (VectorLength2(diffusecolor) > 0)
10485         {
10486                 // q3-style directional shading
10487                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10488                 rsurface.passcolor4f_vertexbuffer = 0;
10489                 rsurface.passcolor4f_bufferoffset = 0;
10490                 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)
10491                 {
10492                         if ((f = DotProduct(n, lightdir)) > 0)
10493                                 VectorMA(ambientcolor, f, diffusecolor, c);
10494                         else
10495                                 VectorCopy(ambientcolor, c);
10496                         c[3] = alpha;
10497                 }
10498                 *r = 1;
10499                 *g = 1;
10500                 *b = 1;
10501                 *a = 1;
10502                 *applycolor = false;
10503         }
10504         else
10505         {
10506                 *r = ambientcolor[0];
10507                 *g = ambientcolor[1];
10508                 *b = ambientcolor[2];
10509                 rsurface.passcolor4f = NULL;
10510                 rsurface.passcolor4f_vertexbuffer = 0;
10511                 rsurface.passcolor4f_bufferoffset = 0;
10512         }
10513 }
10514
10515 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10516 {
10517         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10518         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10519         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10520         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10521         GL_Color(r, g, b, a);
10522         RSurf_DrawBatch();
10523 }
10524
10525 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10526 {
10527         int i;
10528         float f;
10529         const float *v;
10530         float *c;
10531
10532         // fake shading
10533         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10534         rsurface.passcolor4f_vertexbuffer = 0;
10535         rsurface.passcolor4f_bufferoffset = 0;
10536
10537         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10538         {
10539                 f = 1 - RSurf_FogVertex(v);
10540                 c[0] = r;
10541                 c[1] = g;
10542                 c[2] = b;
10543                 c[3] = f * a;
10544         }
10545 }
10546
10547 void RSurf_SetupDepthAndCulling(void)
10548 {
10549         // submodels are biased to avoid z-fighting with world surfaces that they
10550         // may be exactly overlapping (avoids z-fighting artifacts on certain
10551         // doors and things in Quake maps)
10552         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10553         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10554         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10555         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10556 }
10557
10558 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10559 {
10560         // transparent sky would be ridiculous
10561         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10562                 return;
10563         R_SetupShader_Generic_NoTexture(false, false);
10564         skyrenderlater = true;
10565         RSurf_SetupDepthAndCulling();
10566         GL_DepthMask(true);
10567         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10568         // skymasking on them, and Quake3 never did sky masking (unlike
10569         // software Quake and software Quake2), so disable the sky masking
10570         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10571         // and skymasking also looks very bad when noclipping outside the
10572         // level, so don't use it then either.
10573         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10574         {
10575                 R_Mesh_ResetTextureState();
10576                 if (skyrendermasked)
10577                 {
10578                         R_SetupShader_DepthOrShadow(false, false, false);
10579                         // depth-only (masking)
10580                         GL_ColorMask(0,0,0,0);
10581                         // just to make sure that braindead drivers don't draw
10582                         // anything despite that colormask...
10583                         GL_BlendFunc(GL_ZERO, GL_ONE);
10584                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10585                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10586                 }
10587                 else
10588                 {
10589                         R_SetupShader_Generic_NoTexture(false, false);
10590                         // fog sky
10591                         GL_BlendFunc(GL_ONE, GL_ZERO);
10592                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10593                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10594                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10595                 }
10596                 RSurf_DrawBatch();
10597                 if (skyrendermasked)
10598                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10599         }
10600         R_Mesh_ResetTextureState();
10601         GL_Color(1, 1, 1, 1);
10602 }
10603
10604 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10605 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10606 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10607 {
10608         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10609                 return;
10610         if (prepass)
10611         {
10612                 // render screenspace normalmap to texture
10613                 GL_DepthMask(true);
10614                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10615                 RSurf_DrawBatch();
10616                 return;
10617         }
10618
10619         // bind lightmap texture
10620
10621         // water/refraction/reflection/camera surfaces have to be handled specially
10622         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10623         {
10624                 int start, end, startplaneindex;
10625                 for (start = 0;start < texturenumsurfaces;start = end)
10626                 {
10627                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10628                         if(startplaneindex < 0)
10629                         {
10630                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10631                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10632                                 end = start + 1;
10633                                 continue;
10634                         }
10635                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10636                                 ;
10637                         // now that we have a batch using the same planeindex, render it
10638                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10639                         {
10640                                 // render water or distortion background
10641                                 GL_DepthMask(true);
10642                                 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);
10643                                 RSurf_DrawBatch();
10644                                 // blend surface on top
10645                                 GL_DepthMask(false);
10646                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10647                                 RSurf_DrawBatch();
10648                         }
10649                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10650                         {
10651                                 // render surface with reflection texture as input
10652                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10653                                 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);
10654                                 RSurf_DrawBatch();
10655                         }
10656                 }
10657                 return;
10658         }
10659
10660         // render surface batch normally
10661         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10662         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);
10663         RSurf_DrawBatch();
10664 }
10665
10666 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10667 {
10668         // OpenGL 1.3 path - anything not completely ancient
10669         qboolean applycolor;
10670         qboolean applyfog;
10671         int layerindex;
10672         const texturelayer_t *layer;
10673         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);
10674         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10675
10676         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10677         {
10678                 vec4_t layercolor;
10679                 int layertexrgbscale;
10680                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10681                 {
10682                         if (layerindex == 0)
10683                                 GL_AlphaTest(true);
10684                         else
10685                         {
10686                                 GL_AlphaTest(false);
10687                                 GL_DepthFunc(GL_EQUAL);
10688                         }
10689                 }
10690                 GL_DepthMask(layer->depthmask && writedepth);
10691                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10692                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10693                 {
10694                         layertexrgbscale = 4;
10695                         VectorScale(layer->color, 0.25f, layercolor);
10696                 }
10697                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10698                 {
10699                         layertexrgbscale = 2;
10700                         VectorScale(layer->color, 0.5f, layercolor);
10701                 }
10702                 else
10703                 {
10704                         layertexrgbscale = 1;
10705                         VectorScale(layer->color, 1.0f, layercolor);
10706                 }
10707                 layercolor[3] = layer->color[3];
10708                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10709                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10710                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10711                 switch (layer->type)
10712                 {
10713                 case TEXTURELAYERTYPE_LITTEXTURE:
10714                         // single-pass lightmapped texture with 2x rgbscale
10715                         R_Mesh_TexBind(0, r_texture_white);
10716                         R_Mesh_TexMatrix(0, NULL);
10717                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10718                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10719                         R_Mesh_TexBind(1, layer->texture);
10720                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10721                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10722                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10723                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10724                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10725                         else if (FAKELIGHT_ENABLED)
10726                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10727                         else if (rsurface.uselightmaptexture)
10728                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10729                         else
10730                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10731                         break;
10732                 case TEXTURELAYERTYPE_TEXTURE:
10733                         // singletexture unlit texture with transparency support
10734                         R_Mesh_TexBind(0, layer->texture);
10735                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10736                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10737                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10738                         R_Mesh_TexBind(1, 0);
10739                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10740                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10741                         break;
10742                 case TEXTURELAYERTYPE_FOG:
10743                         // singletexture fogging
10744                         if (layer->texture)
10745                         {
10746                                 R_Mesh_TexBind(0, layer->texture);
10747                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10748                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10749                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10750                         }
10751                         else
10752                         {
10753                                 R_Mesh_TexBind(0, 0);
10754                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10755                         }
10756                         R_Mesh_TexBind(1, 0);
10757                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10758                         // generate a color array for the fog pass
10759                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10760                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10761                         RSurf_DrawBatch();
10762                         break;
10763                 default:
10764                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10765                 }
10766         }
10767         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10768         {
10769                 GL_DepthFunc(GL_LEQUAL);
10770                 GL_AlphaTest(false);
10771         }
10772 }
10773
10774 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10775 {
10776         // OpenGL 1.1 - crusty old voodoo path
10777         qboolean applyfog;
10778         int layerindex;
10779         const texturelayer_t *layer;
10780         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);
10781         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10782
10783         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10784         {
10785                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10786                 {
10787                         if (layerindex == 0)
10788                                 GL_AlphaTest(true);
10789                         else
10790                         {
10791                                 GL_AlphaTest(false);
10792                                 GL_DepthFunc(GL_EQUAL);
10793                         }
10794                 }
10795                 GL_DepthMask(layer->depthmask && writedepth);
10796                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10797                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10798                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10799                 switch (layer->type)
10800                 {
10801                 case TEXTURELAYERTYPE_LITTEXTURE:
10802                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10803                         {
10804                                 // two-pass lit texture with 2x rgbscale
10805                                 // first the lightmap pass
10806                                 R_Mesh_TexBind(0, r_texture_white);
10807                                 R_Mesh_TexMatrix(0, NULL);
10808                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10809                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10810                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10811                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10812                                 else if (FAKELIGHT_ENABLED)
10813                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10814                                 else if (rsurface.uselightmaptexture)
10815                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10816                                 else
10817                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10818                                 // then apply the texture to it
10819                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10820                                 R_Mesh_TexBind(0, layer->texture);
10821                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10822                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10823                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10824                                 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);
10825                         }
10826                         else
10827                         {
10828                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10829                                 R_Mesh_TexBind(0, layer->texture);
10830                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10831                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10832                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10833                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10834                                         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);
10835                                 else if (FAKELIGHT_ENABLED)
10836                                         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);
10837                                 else
10838                                         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);
10839                         }
10840                         break;
10841                 case TEXTURELAYERTYPE_TEXTURE:
10842                         // singletexture unlit texture with transparency support
10843                         R_Mesh_TexBind(0, layer->texture);
10844                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10845                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10846                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10847                         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);
10848                         break;
10849                 case TEXTURELAYERTYPE_FOG:
10850                         // singletexture fogging
10851                         if (layer->texture)
10852                         {
10853                                 R_Mesh_TexBind(0, layer->texture);
10854                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10855                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10856                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10857                         }
10858                         else
10859                         {
10860                                 R_Mesh_TexBind(0, 0);
10861                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10862                         }
10863                         // generate a color array for the fog pass
10864                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10865                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10866                         RSurf_DrawBatch();
10867                         break;
10868                 default:
10869                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10870                 }
10871         }
10872         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10873         {
10874                 GL_DepthFunc(GL_LEQUAL);
10875                 GL_AlphaTest(false);
10876         }
10877 }
10878
10879 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10880 {
10881         int vi;
10882         int j;
10883         r_vertexgeneric_t *batchvertex;
10884         float c[4];
10885
10886 //      R_Mesh_ResetTextureState();
10887         R_SetupShader_Generic_NoTexture(false, false);
10888
10889         if(rsurface.texture && rsurface.texture->currentskinframe)
10890         {
10891                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10892                 c[3] *= rsurface.texture->currentalpha;
10893         }
10894         else
10895         {
10896                 c[0] = 1;
10897                 c[1] = 0;
10898                 c[2] = 1;
10899                 c[3] = 1;
10900         }
10901
10902         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10903         {
10904                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10905                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10906                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10907         }
10908
10909         // brighten it up (as texture value 127 means "unlit")
10910         c[0] *= 2 * r_refdef.view.colorscale;
10911         c[1] *= 2 * r_refdef.view.colorscale;
10912         c[2] *= 2 * r_refdef.view.colorscale;
10913
10914         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10915                 c[3] *= r_wateralpha.value;
10916
10917         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10918         {
10919                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10920                 GL_DepthMask(false);
10921         }
10922         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10923         {
10924                 GL_BlendFunc(GL_ONE, GL_ONE);
10925                 GL_DepthMask(false);
10926         }
10927         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10928         {
10929                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10930                 GL_DepthMask(false);
10931         }
10932         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10933         {
10934                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10935                 GL_DepthMask(false);
10936         }
10937         else
10938         {
10939                 GL_BlendFunc(GL_ONE, GL_ZERO);
10940                 GL_DepthMask(writedepth);
10941         }
10942
10943         if (r_showsurfaces.integer == 3)
10944         {
10945                 rsurface.passcolor4f = NULL;
10946
10947                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10948                 {
10949                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10950
10951                         rsurface.passcolor4f = NULL;
10952                         rsurface.passcolor4f_vertexbuffer = 0;
10953                         rsurface.passcolor4f_bufferoffset = 0;
10954                 }
10955                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10956                 {
10957                         qboolean applycolor = true;
10958                         float one = 1.0;
10959
10960                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10961
10962                         r_refdef.lightmapintensity = 1;
10963                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10964                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10965                 }
10966                 else if (FAKELIGHT_ENABLED)
10967                 {
10968                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10969
10970                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10971                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10972                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10973                 }
10974                 else
10975                 {
10976                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10977
10978                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10979                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10980                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10981                 }
10982
10983                 if(!rsurface.passcolor4f)
10984                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10985
10986                 RSurf_DrawBatch_GL11_ApplyAmbient();
10987                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10988                 if(r_refdef.fogenabled)
10989                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10990                 RSurf_DrawBatch_GL11_ClampColor();
10991
10992                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10993                 R_SetupShader_Generic_NoTexture(false, false);
10994                 RSurf_DrawBatch();
10995         }
10996         else if (!r_refdef.view.showdebug)
10997         {
10998                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10999                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11000                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11001                 {
11002                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11003                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11004                 }
11005                 R_Mesh_PrepareVertices_Generic_Unlock();
11006                 RSurf_DrawBatch();
11007         }
11008         else if (r_showsurfaces.integer == 4)
11009         {
11010                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11011                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11012                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11013                 {
11014                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11015                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11016                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11017                 }
11018                 R_Mesh_PrepareVertices_Generic_Unlock();
11019                 RSurf_DrawBatch();
11020         }
11021         else if (r_showsurfaces.integer == 2)
11022         {
11023                 const int *e;
11024                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11025                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11026                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11027                 {
11028                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11029                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11030                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11031                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11032                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11033                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11034                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11035                 }
11036                 R_Mesh_PrepareVertices_Generic_Unlock();
11037                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11038         }
11039         else
11040         {
11041                 int texturesurfaceindex;
11042                 int k;
11043                 const msurface_t *surface;
11044                 float surfacecolor4f[4];
11045                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11046                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11047                 vi = 0;
11048                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11049                 {
11050                         surface = texturesurfacelist[texturesurfaceindex];
11051                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11052                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11053                         for (j = 0;j < surface->num_vertices;j++)
11054                         {
11055                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11056                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11057                                 vi++;
11058                         }
11059                 }
11060                 R_Mesh_PrepareVertices_Generic_Unlock();
11061                 RSurf_DrawBatch();
11062         }
11063 }
11064
11065 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11066 {
11067         CHECKGLERROR
11068         RSurf_SetupDepthAndCulling();
11069         if (r_showsurfaces.integer)
11070         {
11071                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11072                 return;
11073         }
11074         switch (vid.renderpath)
11075         {
11076         case RENDERPATH_GL20:
11077         case RENDERPATH_D3D9:
11078         case RENDERPATH_D3D10:
11079         case RENDERPATH_D3D11:
11080         case RENDERPATH_SOFT:
11081         case RENDERPATH_GLES2:
11082                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11083                 break;
11084         case RENDERPATH_GL13:
11085         case RENDERPATH_GLES1:
11086                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11087                 break;
11088         case RENDERPATH_GL11:
11089                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11090                 break;
11091         }
11092         CHECKGLERROR
11093 }
11094
11095 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11096 {
11097         CHECKGLERROR
11098         RSurf_SetupDepthAndCulling();
11099         if (r_showsurfaces.integer)
11100         {
11101                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11102                 return;
11103         }
11104         switch (vid.renderpath)
11105         {
11106         case RENDERPATH_GL20:
11107         case RENDERPATH_D3D9:
11108         case RENDERPATH_D3D10:
11109         case RENDERPATH_D3D11:
11110         case RENDERPATH_SOFT:
11111         case RENDERPATH_GLES2:
11112                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11113                 break;
11114         case RENDERPATH_GL13:
11115         case RENDERPATH_GLES1:
11116                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11117                 break;
11118         case RENDERPATH_GL11:
11119                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11120                 break;
11121         }
11122         CHECKGLERROR
11123 }
11124
11125 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11126 {
11127         int i, j;
11128         int texturenumsurfaces, endsurface;
11129         texture_t *texture;
11130         const msurface_t *surface;
11131         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11132
11133         // if the model is static it doesn't matter what value we give for
11134         // wantnormals and wanttangents, so this logic uses only rules applicable
11135         // to a model, knowing that they are meaningless otherwise
11136         if (ent == r_refdef.scene.worldentity)
11137                 RSurf_ActiveWorldEntity();
11138         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11139                 RSurf_ActiveModelEntity(ent, false, false, false);
11140         else
11141         {
11142                 switch (vid.renderpath)
11143                 {
11144                 case RENDERPATH_GL20:
11145                 case RENDERPATH_D3D9:
11146                 case RENDERPATH_D3D10:
11147                 case RENDERPATH_D3D11:
11148                 case RENDERPATH_SOFT:
11149                 case RENDERPATH_GLES2:
11150                         RSurf_ActiveModelEntity(ent, true, true, false);
11151                         break;
11152                 case RENDERPATH_GL11:
11153                 case RENDERPATH_GL13:
11154                 case RENDERPATH_GLES1:
11155                         RSurf_ActiveModelEntity(ent, true, false, false);
11156                         break;
11157                 }
11158         }
11159
11160         if (r_transparentdepthmasking.integer)
11161         {
11162                 qboolean setup = false;
11163                 for (i = 0;i < numsurfaces;i = j)
11164                 {
11165                         j = i + 1;
11166                         surface = rsurface.modelsurfaces + surfacelist[i];
11167                         texture = surface->texture;
11168                         rsurface.texture = R_GetCurrentTexture(texture);
11169                         rsurface.lightmaptexture = NULL;
11170                         rsurface.deluxemaptexture = NULL;
11171                         rsurface.uselightmaptexture = false;
11172                         // scan ahead until we find a different texture
11173                         endsurface = min(i + 1024, numsurfaces);
11174                         texturenumsurfaces = 0;
11175                         texturesurfacelist[texturenumsurfaces++] = surface;
11176                         for (;j < endsurface;j++)
11177                         {
11178                                 surface = rsurface.modelsurfaces + surfacelist[j];
11179                                 if (texture != surface->texture)
11180                                         break;
11181                                 texturesurfacelist[texturenumsurfaces++] = surface;
11182                         }
11183                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11184                                 continue;
11185                         // render the range of surfaces as depth
11186                         if (!setup)
11187                         {
11188                                 setup = true;
11189                                 GL_ColorMask(0,0,0,0);
11190                                 GL_Color(1,1,1,1);
11191                                 GL_DepthTest(true);
11192                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11193                                 GL_DepthMask(true);
11194 //                              R_Mesh_ResetTextureState();
11195                         }
11196                         RSurf_SetupDepthAndCulling();
11197                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11198                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11199                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11200                         RSurf_DrawBatch();
11201                 }
11202                 if (setup)
11203                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11204         }
11205
11206         for (i = 0;i < numsurfaces;i = j)
11207         {
11208                 j = i + 1;
11209                 surface = rsurface.modelsurfaces + surfacelist[i];
11210                 texture = surface->texture;
11211                 rsurface.texture = R_GetCurrentTexture(texture);
11212                 // scan ahead until we find a different texture
11213                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11214                 texturenumsurfaces = 0;
11215                 texturesurfacelist[texturenumsurfaces++] = surface;
11216                 if(FAKELIGHT_ENABLED)
11217                 {
11218                         rsurface.lightmaptexture = NULL;
11219                         rsurface.deluxemaptexture = NULL;
11220                         rsurface.uselightmaptexture = false;
11221                         for (;j < endsurface;j++)
11222                         {
11223                                 surface = rsurface.modelsurfaces + surfacelist[j];
11224                                 if (texture != surface->texture)
11225                                         break;
11226                                 texturesurfacelist[texturenumsurfaces++] = surface;
11227                         }
11228                 }
11229                 else
11230                 {
11231                         rsurface.lightmaptexture = surface->lightmaptexture;
11232                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11233                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11234                         for (;j < endsurface;j++)
11235                         {
11236                                 surface = rsurface.modelsurfaces + surfacelist[j];
11237                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11238                                         break;
11239                                 texturesurfacelist[texturenumsurfaces++] = surface;
11240                         }
11241                 }
11242                 // render the range of surfaces
11243                 if (ent == r_refdef.scene.worldentity)
11244                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11245                 else
11246                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11247         }
11248         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11249 }
11250
11251 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11252 {
11253         // transparent surfaces get pushed off into the transparent queue
11254         int surfacelistindex;
11255         const msurface_t *surface;
11256         vec3_t tempcenter, center;
11257         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11258         {
11259                 surface = texturesurfacelist[surfacelistindex];
11260                 if (r_transparent_sortsurfacesbynearest.integer)
11261                 {
11262                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11263                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11264                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11265                 }
11266                 else
11267                 {
11268                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11269                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11270                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11271                 }
11272                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11273                 if (rsurface.entity->transparent_offset) // transparent offset
11274                 {
11275                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11276                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11277                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11278                 }
11279                 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);
11280         }
11281 }
11282
11283 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11284 {
11285         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11286                 return;
11287         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11288                 return;
11289         RSurf_SetupDepthAndCulling();
11290         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11291         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11292         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11293         RSurf_DrawBatch();
11294 }
11295
11296 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11297 {
11298         CHECKGLERROR
11299         if (depthonly)
11300                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11301         else if (prepass)
11302         {
11303                 if (!rsurface.texture->currentnumlayers)
11304                         return;
11305                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11306                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11307                 else
11308                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11309         }
11310         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11311                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11312         else if (!rsurface.texture->currentnumlayers)
11313                 return;
11314         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11315         {
11316                 // in the deferred case, transparent surfaces were queued during prepass
11317                 if (!r_shadow_usingdeferredprepass)
11318                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11319         }
11320         else
11321         {
11322                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11323                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11324         }
11325         CHECKGLERROR
11326 }
11327
11328 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11329 {
11330         int i, j;
11331         texture_t *texture;
11332         R_FrameData_SetMark();
11333         // break the surface list down into batches by texture and use of lightmapping
11334         for (i = 0;i < numsurfaces;i = j)
11335         {
11336                 j = i + 1;
11337                 // texture is the base texture pointer, rsurface.texture is the
11338                 // current frame/skin the texture is directing us to use (for example
11339                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11340                 // use skin 1 instead)
11341                 texture = surfacelist[i]->texture;
11342                 rsurface.texture = R_GetCurrentTexture(texture);
11343                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11344                 {
11345                         // if this texture is not the kind we want, skip ahead to the next one
11346                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11347                                 ;
11348                         continue;
11349                 }
11350                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11351                 {
11352                         rsurface.lightmaptexture = NULL;
11353                         rsurface.deluxemaptexture = NULL;
11354                         rsurface.uselightmaptexture = false;
11355                         // simply scan ahead until we find a different texture or lightmap state
11356                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11357                                 ;
11358                 }
11359                 else
11360                 {
11361                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11362                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11363                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11364                         // simply scan ahead until we find a different texture or lightmap state
11365                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11366                                 ;
11367                 }
11368                 // render the range of surfaces
11369                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11370         }
11371         R_FrameData_ReturnToMark();
11372 }
11373
11374 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11375 {
11376         CHECKGLERROR
11377         if (depthonly)
11378                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11379         else if (prepass)
11380         {
11381                 if (!rsurface.texture->currentnumlayers)
11382                         return;
11383                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11384                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11385                 else
11386                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11387         }
11388         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11389                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11390         else if (!rsurface.texture->currentnumlayers)
11391                 return;
11392         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11393         {
11394                 // in the deferred case, transparent surfaces were queued during prepass
11395                 if (!r_shadow_usingdeferredprepass)
11396                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11397         }
11398         else
11399         {
11400                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11401                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11402         }
11403         CHECKGLERROR
11404 }
11405
11406 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11407 {
11408         int i, j;
11409         texture_t *texture;
11410         R_FrameData_SetMark();
11411         // break the surface list down into batches by texture and use of lightmapping
11412         for (i = 0;i < numsurfaces;i = j)
11413         {
11414                 j = i + 1;
11415                 // texture is the base texture pointer, rsurface.texture is the
11416                 // current frame/skin the texture is directing us to use (for example
11417                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11418                 // use skin 1 instead)
11419                 texture = surfacelist[i]->texture;
11420                 rsurface.texture = R_GetCurrentTexture(texture);
11421                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11422                 {
11423                         // if this texture is not the kind we want, skip ahead to the next one
11424                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11425                                 ;
11426                         continue;
11427                 }
11428                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11429                 {
11430                         rsurface.lightmaptexture = NULL;
11431                         rsurface.deluxemaptexture = NULL;
11432                         rsurface.uselightmaptexture = false;
11433                         // simply scan ahead until we find a different texture or lightmap state
11434                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11435                                 ;
11436                 }
11437                 else
11438                 {
11439                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11440                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11441                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11442                         // simply scan ahead until we find a different texture or lightmap state
11443                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11444                                 ;
11445                 }
11446                 // render the range of surfaces
11447                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11448         }
11449         R_FrameData_ReturnToMark();
11450 }
11451
11452 float locboxvertex3f[6*4*3] =
11453 {
11454         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11455         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11456         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11457         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11458         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11459         1,0,0, 0,0,0, 0,1,0, 1,1,0
11460 };
11461
11462 unsigned short locboxelements[6*2*3] =
11463 {
11464          0, 1, 2, 0, 2, 3,
11465          4, 5, 6, 4, 6, 7,
11466          8, 9,10, 8,10,11,
11467         12,13,14, 12,14,15,
11468         16,17,18, 16,18,19,
11469         20,21,22, 20,22,23
11470 };
11471
11472 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11473 {
11474         int i, j;
11475         cl_locnode_t *loc = (cl_locnode_t *)ent;
11476         vec3_t mins, size;
11477         float vertex3f[6*4*3];
11478         CHECKGLERROR
11479         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11480         GL_DepthMask(false);
11481         GL_DepthRange(0, 1);
11482         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11483         GL_DepthTest(true);
11484         GL_CullFace(GL_NONE);
11485         R_EntityMatrix(&identitymatrix);
11486
11487 //      R_Mesh_ResetTextureState();
11488
11489         i = surfacelist[0];
11490         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11491                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11492                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11493                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11494
11495         if (VectorCompare(loc->mins, loc->maxs))
11496         {
11497                 VectorSet(size, 2, 2, 2);
11498                 VectorMA(loc->mins, -0.5f, size, mins);
11499         }
11500         else
11501         {
11502                 VectorCopy(loc->mins, mins);
11503                 VectorSubtract(loc->maxs, loc->mins, size);
11504         }
11505
11506         for (i = 0;i < 6*4*3;)
11507                 for (j = 0;j < 3;j++, i++)
11508                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11509
11510         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11511         R_SetupShader_Generic_NoTexture(false, false);
11512         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11513 }
11514
11515 void R_DrawLocs(void)
11516 {
11517         int index;
11518         cl_locnode_t *loc, *nearestloc;
11519         vec3_t center;
11520         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11521         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11522         {
11523                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11524                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11525         }
11526 }
11527
11528 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11529 {
11530         if (decalsystem->decals)
11531                 Mem_Free(decalsystem->decals);
11532         memset(decalsystem, 0, sizeof(*decalsystem));
11533 }
11534
11535 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)
11536 {
11537         tridecal_t *decal;
11538         tridecal_t *decals;
11539         int i;
11540
11541         // expand or initialize the system
11542         if (decalsystem->maxdecals <= decalsystem->numdecals)
11543         {
11544                 decalsystem_t old = *decalsystem;
11545                 qboolean useshortelements;
11546                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11547                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11548                 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)));
11549                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11550                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11551                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11552                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11553                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11554                 if (decalsystem->numdecals)
11555                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11556                 if (old.decals)
11557                         Mem_Free(old.decals);
11558                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11559                         decalsystem->element3i[i] = i;
11560                 if (useshortelements)
11561                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11562                                 decalsystem->element3s[i] = i;
11563         }
11564
11565         // grab a decal and search for another free slot for the next one
11566         decals = decalsystem->decals;
11567         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11568         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11569                 ;
11570         decalsystem->freedecal = i;
11571         if (decalsystem->numdecals <= i)
11572                 decalsystem->numdecals = i + 1;
11573
11574         // initialize the decal
11575         decal->lived = 0;
11576         decal->triangleindex = triangleindex;
11577         decal->surfaceindex = surfaceindex;
11578         decal->decalsequence = decalsequence;
11579         decal->color4f[0][0] = c0[0];
11580         decal->color4f[0][1] = c0[1];
11581         decal->color4f[0][2] = c0[2];
11582         decal->color4f[0][3] = 1;
11583         decal->color4f[1][0] = c1[0];
11584         decal->color4f[1][1] = c1[1];
11585         decal->color4f[1][2] = c1[2];
11586         decal->color4f[1][3] = 1;
11587         decal->color4f[2][0] = c2[0];
11588         decal->color4f[2][1] = c2[1];
11589         decal->color4f[2][2] = c2[2];
11590         decal->color4f[2][3] = 1;
11591         decal->vertex3f[0][0] = v0[0];
11592         decal->vertex3f[0][1] = v0[1];
11593         decal->vertex3f[0][2] = v0[2];
11594         decal->vertex3f[1][0] = v1[0];
11595         decal->vertex3f[1][1] = v1[1];
11596         decal->vertex3f[1][2] = v1[2];
11597         decal->vertex3f[2][0] = v2[0];
11598         decal->vertex3f[2][1] = v2[1];
11599         decal->vertex3f[2][2] = v2[2];
11600         decal->texcoord2f[0][0] = t0[0];
11601         decal->texcoord2f[0][1] = t0[1];
11602         decal->texcoord2f[1][0] = t1[0];
11603         decal->texcoord2f[1][1] = t1[1];
11604         decal->texcoord2f[2][0] = t2[0];
11605         decal->texcoord2f[2][1] = t2[1];
11606         TriangleNormal(v0, v1, v2, decal->plane);
11607         VectorNormalize(decal->plane);
11608         decal->plane[3] = DotProduct(v0, decal->plane);
11609 }
11610
11611 extern cvar_t cl_decals_bias;
11612 extern cvar_t cl_decals_models;
11613 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11614 // baseparms, parms, temps
11615 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)
11616 {
11617         int cornerindex;
11618         int index;
11619         float v[9][3];
11620         const float *vertex3f;
11621         const float *normal3f;
11622         int numpoints;
11623         float points[2][9][3];
11624         float temp[3];
11625         float tc[9][2];
11626         float f;
11627         float c[9][4];
11628         const int *e;
11629
11630         e = rsurface.modelelement3i + 3*triangleindex;
11631
11632         vertex3f = rsurface.modelvertex3f;
11633         normal3f = rsurface.modelnormal3f;
11634
11635         if (normal3f)
11636         {
11637                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11638                 {
11639                         index = 3*e[cornerindex];
11640                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11641                 }
11642         }
11643         else
11644         {
11645                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11646                 {
11647                         index = 3*e[cornerindex];
11648                         VectorCopy(vertex3f + index, v[cornerindex]);
11649                 }
11650         }
11651
11652         // cull backfaces
11653         //TriangleNormal(v[0], v[1], v[2], normal);
11654         //if (DotProduct(normal, localnormal) < 0.0f)
11655         //      continue;
11656         // clip by each of the box planes formed from the projection matrix
11657         // if anything survives, we emit the decal
11658         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]);
11659         if (numpoints < 3)
11660                 return;
11661         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]);
11662         if (numpoints < 3)
11663                 return;
11664         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]);
11665         if (numpoints < 3)
11666                 return;
11667         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]);
11668         if (numpoints < 3)
11669                 return;
11670         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]);
11671         if (numpoints < 3)
11672                 return;
11673         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]);
11674         if (numpoints < 3)
11675                 return;
11676         // some part of the triangle survived, so we have to accept it...
11677         if (dynamic)
11678         {
11679                 // dynamic always uses the original triangle
11680                 numpoints = 3;
11681                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11682                 {
11683                         index = 3*e[cornerindex];
11684                         VectorCopy(vertex3f + index, v[cornerindex]);
11685                 }
11686         }
11687         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11688         {
11689                 // convert vertex positions to texcoords
11690                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11691                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11692                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11693                 // calculate distance fade from the projection origin
11694                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11695                 f = bound(0.0f, f, 1.0f);
11696                 c[cornerindex][0] = r * f;
11697                 c[cornerindex][1] = g * f;
11698                 c[cornerindex][2] = b * f;
11699                 c[cornerindex][3] = 1.0f;
11700                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11701         }
11702         if (dynamic)
11703                 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);
11704         else
11705                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11706                         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);
11707 }
11708 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)
11709 {
11710         matrix4x4_t projection;
11711         decalsystem_t *decalsystem;
11712         qboolean dynamic;
11713         dp_model_t *model;
11714         const msurface_t *surface;
11715         const msurface_t *surfaces;
11716         const int *surfacelist;
11717         const texture_t *texture;
11718         int numtriangles;
11719         int numsurfacelist;
11720         int surfacelistindex;
11721         int surfaceindex;
11722         int triangleindex;
11723         float localorigin[3];
11724         float localnormal[3];
11725         float localmins[3];
11726         float localmaxs[3];
11727         float localsize;
11728         //float normal[3];
11729         float planes[6][4];
11730         float angles[3];
11731         bih_t *bih;
11732         int bih_triangles_count;
11733         int bih_triangles[256];
11734         int bih_surfaces[256];
11735
11736         decalsystem = &ent->decalsystem;
11737         model = ent->model;
11738         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11739         {
11740                 R_DecalSystem_Reset(&ent->decalsystem);
11741                 return;
11742         }
11743
11744         if (!model->brush.data_leafs && !cl_decals_models.integer)
11745         {
11746                 if (decalsystem->model)
11747                         R_DecalSystem_Reset(decalsystem);
11748                 return;
11749         }
11750
11751         if (decalsystem->model != model)
11752                 R_DecalSystem_Reset(decalsystem);
11753         decalsystem->model = model;
11754
11755         RSurf_ActiveModelEntity(ent, true, false, false);
11756
11757         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11758         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11759         VectorNormalize(localnormal);
11760         localsize = worldsize*rsurface.inversematrixscale;
11761         localmins[0] = localorigin[0] - localsize;
11762         localmins[1] = localorigin[1] - localsize;
11763         localmins[2] = localorigin[2] - localsize;
11764         localmaxs[0] = localorigin[0] + localsize;
11765         localmaxs[1] = localorigin[1] + localsize;
11766         localmaxs[2] = localorigin[2] + localsize;
11767
11768         //VectorCopy(localnormal, planes[4]);
11769         //VectorVectors(planes[4], planes[2], planes[0]);
11770         AnglesFromVectors(angles, localnormal, NULL, false);
11771         AngleVectors(angles, planes[0], planes[2], planes[4]);
11772         VectorNegate(planes[0], planes[1]);
11773         VectorNegate(planes[2], planes[3]);
11774         VectorNegate(planes[4], planes[5]);
11775         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11776         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11777         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11778         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11779         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11780         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11781
11782 #if 1
11783 // works
11784 {
11785         matrix4x4_t forwardprojection;
11786         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11787         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11788 }
11789 #else
11790 // broken
11791 {
11792         float projectionvector[4][3];
11793         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11794         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11795         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11796         projectionvector[0][0] = planes[0][0] * ilocalsize;
11797         projectionvector[0][1] = planes[1][0] * ilocalsize;
11798         projectionvector[0][2] = planes[2][0] * ilocalsize;
11799         projectionvector[1][0] = planes[0][1] * ilocalsize;
11800         projectionvector[1][1] = planes[1][1] * ilocalsize;
11801         projectionvector[1][2] = planes[2][1] * ilocalsize;
11802         projectionvector[2][0] = planes[0][2] * ilocalsize;
11803         projectionvector[2][1] = planes[1][2] * ilocalsize;
11804         projectionvector[2][2] = planes[2][2] * ilocalsize;
11805         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11806         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11807         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11808         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11809 }
11810 #endif
11811
11812         dynamic = model->surfmesh.isanimated;
11813         numsurfacelist = model->nummodelsurfaces;
11814         surfacelist = model->sortedmodelsurfaces;
11815         surfaces = model->data_surfaces;
11816
11817         bih = NULL;
11818         bih_triangles_count = -1;
11819         if(!dynamic)
11820         {
11821                 if(model->render_bih.numleafs)
11822                         bih = &model->render_bih;
11823                 else if(model->collision_bih.numleafs)
11824                         bih = &model->collision_bih;
11825         }
11826         if(bih)
11827                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11828         if(bih_triangles_count == 0)
11829                 return;
11830         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11831                 return;
11832         if(bih_triangles_count > 0)
11833         {
11834                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11835                 {
11836                         surfaceindex = bih_surfaces[triangleindex];
11837                         surface = surfaces + surfaceindex;
11838                         texture = surface->texture;
11839                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11840                                 continue;
11841                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11842                                 continue;
11843                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11844                 }
11845         }
11846         else
11847         {
11848                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11849                 {
11850                         surfaceindex = surfacelist[surfacelistindex];
11851                         surface = surfaces + surfaceindex;
11852                         // check cull box first because it rejects more than any other check
11853                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11854                                 continue;
11855                         // skip transparent surfaces
11856                         texture = surface->texture;
11857                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11858                                 continue;
11859                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11860                                 continue;
11861                         numtriangles = surface->num_triangles;
11862                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11863                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11864                 }
11865         }
11866 }
11867
11868 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11869 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)
11870 {
11871         int renderentityindex;
11872         float worldmins[3];
11873         float worldmaxs[3];
11874         entity_render_t *ent;
11875
11876         if (!cl_decals_newsystem.integer)
11877                 return;
11878
11879         worldmins[0] = worldorigin[0] - worldsize;
11880         worldmins[1] = worldorigin[1] - worldsize;
11881         worldmins[2] = worldorigin[2] - worldsize;
11882         worldmaxs[0] = worldorigin[0] + worldsize;
11883         worldmaxs[1] = worldorigin[1] + worldsize;
11884         worldmaxs[2] = worldorigin[2] + worldsize;
11885
11886         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11887
11888         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11889         {
11890                 ent = r_refdef.scene.entities[renderentityindex];
11891                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11892                         continue;
11893
11894                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11895         }
11896 }
11897
11898 typedef struct r_decalsystem_splatqueue_s
11899 {
11900         vec3_t worldorigin;
11901         vec3_t worldnormal;
11902         float color[4];
11903         float tcrange[4];
11904         float worldsize;
11905         int decalsequence;
11906 }
11907 r_decalsystem_splatqueue_t;
11908
11909 int r_decalsystem_numqueued = 0;
11910 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11911
11912 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)
11913 {
11914         r_decalsystem_splatqueue_t *queue;
11915
11916         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11917                 return;
11918
11919         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11920         VectorCopy(worldorigin, queue->worldorigin);
11921         VectorCopy(worldnormal, queue->worldnormal);
11922         Vector4Set(queue->color, r, g, b, a);
11923         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11924         queue->worldsize = worldsize;
11925         queue->decalsequence = cl.decalsequence++;
11926 }
11927
11928 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11929 {
11930         int i;
11931         r_decalsystem_splatqueue_t *queue;
11932
11933         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11934                 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);
11935         r_decalsystem_numqueued = 0;
11936 }
11937
11938 extern cvar_t cl_decals_max;
11939 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11940 {
11941         int i;
11942         decalsystem_t *decalsystem = &ent->decalsystem;
11943         int numdecals;
11944         int killsequence;
11945         tridecal_t *decal;
11946         float frametime;
11947         float lifetime;
11948
11949         if (!decalsystem->numdecals)
11950                 return;
11951
11952         if (r_showsurfaces.integer)
11953                 return;
11954
11955         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11956         {
11957                 R_DecalSystem_Reset(decalsystem);
11958                 return;
11959         }
11960
11961         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11962         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11963
11964         if (decalsystem->lastupdatetime)
11965                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11966         else
11967                 frametime = 0;
11968         decalsystem->lastupdatetime = r_refdef.scene.time;
11969         numdecals = decalsystem->numdecals;
11970
11971         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11972         {
11973                 if (decal->color4f[0][3])
11974                 {
11975                         decal->lived += frametime;
11976                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11977                         {
11978                                 memset(decal, 0, sizeof(*decal));
11979                                 if (decalsystem->freedecal > i)
11980                                         decalsystem->freedecal = i;
11981                         }
11982                 }
11983         }
11984         decal = decalsystem->decals;
11985         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11986                 numdecals--;
11987
11988         // collapse the array by shuffling the tail decals into the gaps
11989         for (;;)
11990         {
11991                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11992                         decalsystem->freedecal++;
11993                 if (decalsystem->freedecal == numdecals)
11994                         break;
11995                 decal[decalsystem->freedecal] = decal[--numdecals];
11996         }
11997
11998         decalsystem->numdecals = numdecals;
11999
12000         if (numdecals <= 0)
12001         {
12002                 // if there are no decals left, reset decalsystem
12003                 R_DecalSystem_Reset(decalsystem);
12004         }
12005 }
12006
12007 extern skinframe_t *decalskinframe;
12008 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12009 {
12010         int i;
12011         decalsystem_t *decalsystem = &ent->decalsystem;
12012         int numdecals;
12013         tridecal_t *decal;
12014         float faderate;
12015         float alpha;
12016         float *v3f;
12017         float *c4f;
12018         float *t2f;
12019         const int *e;
12020         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12021         int numtris = 0;
12022
12023         numdecals = decalsystem->numdecals;
12024         if (!numdecals)
12025                 return;
12026
12027         if (r_showsurfaces.integer)
12028                 return;
12029
12030         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12031         {
12032                 R_DecalSystem_Reset(decalsystem);
12033                 return;
12034         }
12035
12036         // if the model is static it doesn't matter what value we give for
12037         // wantnormals and wanttangents, so this logic uses only rules applicable
12038         // to a model, knowing that they are meaningless otherwise
12039         if (ent == r_refdef.scene.worldentity)
12040                 RSurf_ActiveWorldEntity();
12041         else
12042                 RSurf_ActiveModelEntity(ent, false, false, false);
12043
12044         decalsystem->lastupdatetime = r_refdef.scene.time;
12045
12046         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12047
12048         // update vertex positions for animated models
12049         v3f = decalsystem->vertex3f;
12050         c4f = decalsystem->color4f;
12051         t2f = decalsystem->texcoord2f;
12052         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12053         {
12054                 if (!decal->color4f[0][3])
12055                         continue;
12056
12057                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12058                         continue;
12059
12060                 // skip backfaces
12061                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12062                         continue;
12063
12064                 // update color values for fading decals
12065                 if (decal->lived >= cl_decals_time.value)
12066                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12067                 else
12068                         alpha = 1.0f;
12069
12070                 c4f[ 0] = decal->color4f[0][0] * alpha;
12071                 c4f[ 1] = decal->color4f[0][1] * alpha;
12072                 c4f[ 2] = decal->color4f[0][2] * alpha;
12073                 c4f[ 3] = 1;
12074                 c4f[ 4] = decal->color4f[1][0] * alpha;
12075                 c4f[ 5] = decal->color4f[1][1] * alpha;
12076                 c4f[ 6] = decal->color4f[1][2] * alpha;
12077                 c4f[ 7] = 1;
12078                 c4f[ 8] = decal->color4f[2][0] * alpha;
12079                 c4f[ 9] = decal->color4f[2][1] * alpha;
12080                 c4f[10] = decal->color4f[2][2] * alpha;
12081                 c4f[11] = 1;
12082
12083                 t2f[0] = decal->texcoord2f[0][0];
12084                 t2f[1] = decal->texcoord2f[0][1];
12085                 t2f[2] = decal->texcoord2f[1][0];
12086                 t2f[3] = decal->texcoord2f[1][1];
12087                 t2f[4] = decal->texcoord2f[2][0];
12088                 t2f[5] = decal->texcoord2f[2][1];
12089
12090                 // update vertex positions for animated models
12091                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12092                 {
12093                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12094                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12095                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12096                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12097                 }
12098                 else
12099                 {
12100                         VectorCopy(decal->vertex3f[0], v3f);
12101                         VectorCopy(decal->vertex3f[1], v3f + 3);
12102                         VectorCopy(decal->vertex3f[2], v3f + 6);
12103                 }
12104
12105                 if (r_refdef.fogenabled)
12106                 {
12107                         alpha = RSurf_FogVertex(v3f);
12108                         VectorScale(c4f, alpha, c4f);
12109                         alpha = RSurf_FogVertex(v3f + 3);
12110                         VectorScale(c4f + 4, alpha, c4f + 4);
12111                         alpha = RSurf_FogVertex(v3f + 6);
12112                         VectorScale(c4f + 8, alpha, c4f + 8);
12113                 }
12114
12115                 v3f += 9;
12116                 c4f += 12;
12117                 t2f += 6;
12118                 numtris++;
12119         }
12120
12121         if (numtris > 0)
12122         {
12123                 r_refdef.stats[r_stat_drawndecals] += numtris;
12124
12125                 // now render the decals all at once
12126                 // (this assumes they all use one particle font texture!)
12127                 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);
12128 //              R_Mesh_ResetTextureState();
12129                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12130                 GL_DepthMask(false);
12131                 GL_DepthRange(0, 1);
12132                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12133                 GL_DepthTest(true);
12134                 GL_CullFace(GL_NONE);
12135                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12136                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12137                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12138         }
12139 }
12140
12141 static void R_DrawModelDecals(void)
12142 {
12143         int i, numdecals;
12144
12145         // fade faster when there are too many decals
12146         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12147         for (i = 0;i < r_refdef.scene.numentities;i++)
12148                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12149
12150         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12151         for (i = 0;i < r_refdef.scene.numentities;i++)
12152                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12153                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12154
12155         R_DecalSystem_ApplySplatEntitiesQueue();
12156
12157         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12158         for (i = 0;i < r_refdef.scene.numentities;i++)
12159                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12160
12161         r_refdef.stats[r_stat_totaldecals] += numdecals;
12162
12163         if (r_showsurfaces.integer)
12164                 return;
12165
12166         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12167
12168         for (i = 0;i < r_refdef.scene.numentities;i++)
12169         {
12170                 if (!r_refdef.viewcache.entityvisible[i])
12171                         continue;
12172                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12173                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12174         }
12175 }
12176
12177 extern cvar_t mod_collision_bih;
12178 static void R_DrawDebugModel(void)
12179 {
12180         entity_render_t *ent = rsurface.entity;
12181         int i, j, k, l, flagsmask;
12182         const msurface_t *surface;
12183         dp_model_t *model = ent->model;
12184         vec3_t v;
12185
12186         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12187                 return;
12188
12189         if (r_showoverdraw.value > 0)
12190         {
12191                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12192                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12193                 R_SetupShader_Generic_NoTexture(false, false);
12194                 GL_DepthTest(false);
12195                 GL_DepthMask(false);
12196                 GL_DepthRange(0, 1);
12197                 GL_BlendFunc(GL_ONE, GL_ONE);
12198                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12199                 {
12200                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12201                                 continue;
12202                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12203                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12204                         {
12205                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12206                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12207                                 if (!rsurface.texture->currentlayers->depthmask)
12208                                         GL_Color(c, 0, 0, 1.0f);
12209                                 else if (ent == r_refdef.scene.worldentity)
12210                                         GL_Color(c, c, c, 1.0f);
12211                                 else
12212                                         GL_Color(0, c, 0, 1.0f);
12213                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12214                                 RSurf_DrawBatch();
12215                         }
12216                 }
12217                 rsurface.texture = NULL;
12218         }
12219
12220         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12221
12222 //      R_Mesh_ResetTextureState();
12223         R_SetupShader_Generic_NoTexture(false, false);
12224         GL_DepthRange(0, 1);
12225         GL_DepthTest(!r_showdisabledepthtest.integer);
12226         GL_DepthMask(false);
12227         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12228
12229         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12230         {
12231                 int triangleindex;
12232                 int bihleafindex;
12233                 qboolean cullbox = false;
12234                 const q3mbrush_t *brush;
12235                 const bih_t *bih = &model->collision_bih;
12236                 const bih_leaf_t *bihleaf;
12237                 float vertex3f[3][3];
12238                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12239                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12240                 {
12241                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12242                                 continue;
12243                         switch (bihleaf->type)
12244                         {
12245                         case BIH_BRUSH:
12246                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12247                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12248                                 {
12249                                         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);
12250                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12251                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12252                                 }
12253                                 break;
12254                         case BIH_COLLISIONTRIANGLE:
12255                                 triangleindex = bihleaf->itemindex;
12256                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12257                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12258                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12259                                 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);
12260                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12261                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12262                                 break;
12263                         case BIH_RENDERTRIANGLE:
12264                                 triangleindex = bihleaf->itemindex;
12265                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12266                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12267                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12268                                 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);
12269                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12270                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12271                                 break;
12272                         }
12273                 }
12274         }
12275
12276         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12277
12278 #ifndef USE_GLES2
12279         if (r_showtris.integer && qglPolygonMode)
12280         {
12281                 if (r_showdisabledepthtest.integer)
12282                 {
12283                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12284                         GL_DepthMask(false);
12285                 }
12286                 else
12287                 {
12288                         GL_BlendFunc(GL_ONE, GL_ZERO);
12289                         GL_DepthMask(true);
12290                 }
12291                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12292                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12293                 {
12294                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12295                                 continue;
12296                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12297                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12298                         {
12299                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12300                                 if (!rsurface.texture->currentlayers->depthmask)
12301                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12302                                 else if (ent == r_refdef.scene.worldentity)
12303                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12304                                 else
12305                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12306                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12307                                 RSurf_DrawBatch();
12308                         }
12309                 }
12310                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12311                 rsurface.texture = NULL;
12312         }
12313
12314         if (r_shownormals.value != 0 && qglBegin)
12315         {
12316                 if (r_showdisabledepthtest.integer)
12317                 {
12318                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12319                         GL_DepthMask(false);
12320                 }
12321                 else
12322                 {
12323                         GL_BlendFunc(GL_ONE, GL_ZERO);
12324                         GL_DepthMask(true);
12325                 }
12326                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12327                 {
12328                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12329                                 continue;
12330                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12331                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12332                         {
12333                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12334                                 qglBegin(GL_LINES);
12335                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12336                                 {
12337                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12338                                         {
12339                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12340                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12341                                                 qglVertex3f(v[0], v[1], v[2]);
12342                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12343                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12344                                                 qglVertex3f(v[0], v[1], v[2]);
12345                                         }
12346                                 }
12347                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12348                                 {
12349                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12350                                         {
12351                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12352                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12353                                                 qglVertex3f(v[0], v[1], v[2]);
12354                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12355                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12356                                                 qglVertex3f(v[0], v[1], v[2]);
12357                                         }
12358                                 }
12359                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12360                                 {
12361                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12362                                         {
12363                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12364                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12365                                                 qglVertex3f(v[0], v[1], v[2]);
12366                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12367                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12368                                                 qglVertex3f(v[0], v[1], v[2]);
12369                                         }
12370                                 }
12371                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12372                                 {
12373                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12374                                         {
12375                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12376                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12377                                                 qglVertex3f(v[0], v[1], v[2]);
12378                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12379                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12380                                                 qglVertex3f(v[0], v[1], v[2]);
12381                                         }
12382                                 }
12383                                 qglEnd();
12384                                 CHECKGLERROR
12385                         }
12386                 }
12387                 rsurface.texture = NULL;
12388         }
12389 #endif
12390 }
12391
12392 int r_maxsurfacelist = 0;
12393 const msurface_t **r_surfacelist = NULL;
12394 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12395 {
12396         int i, j, endj, flagsmask;
12397         dp_model_t *model = r_refdef.scene.worldmodel;
12398         msurface_t *surfaces;
12399         unsigned char *update;
12400         int numsurfacelist = 0;
12401         if (model == NULL)
12402                 return;
12403
12404         if (r_maxsurfacelist < model->num_surfaces)
12405         {
12406                 r_maxsurfacelist = model->num_surfaces;
12407                 if (r_surfacelist)
12408                         Mem_Free((msurface_t**)r_surfacelist);
12409                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12410         }
12411
12412         RSurf_ActiveWorldEntity();
12413
12414         surfaces = model->data_surfaces;
12415         update = model->brushq1.lightmapupdateflags;
12416
12417         // update light styles on this submodel
12418         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12419         {
12420                 model_brush_lightstyleinfo_t *style;
12421                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12422                 {
12423                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12424                         {
12425                                 int *list = style->surfacelist;
12426                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12427                                 for (j = 0;j < style->numsurfaces;j++)
12428                                         update[list[j]] = true;
12429                         }
12430                 }
12431         }
12432
12433         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12434
12435         if (debug)
12436         {
12437                 R_DrawDebugModel();
12438                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12439                 return;
12440         }
12441
12442         rsurface.lightmaptexture = NULL;
12443         rsurface.deluxemaptexture = NULL;
12444         rsurface.uselightmaptexture = false;
12445         rsurface.texture = NULL;
12446         rsurface.rtlight = NULL;
12447         numsurfacelist = 0;
12448         // add visible surfaces to draw list
12449         for (i = 0;i < model->nummodelsurfaces;i++)
12450         {
12451                 j = model->sortedmodelsurfaces[i];
12452                 if (r_refdef.viewcache.world_surfacevisible[j])
12453                         r_surfacelist[numsurfacelist++] = surfaces + j;
12454         }
12455         // update lightmaps if needed
12456         if (model->brushq1.firstrender)
12457         {
12458                 model->brushq1.firstrender = false;
12459                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12460                         if (update[j])
12461                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12462         }
12463         else if (update)
12464         {
12465                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12466                         if (r_refdef.viewcache.world_surfacevisible[j])
12467                                 if (update[j])
12468                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12469         }
12470         // don't do anything if there were no surfaces
12471         if (!numsurfacelist)
12472         {
12473                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12474                 return;
12475         }
12476         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12477
12478         // add to stats if desired
12479         if (r_speeds.integer && !skysurfaces && !depthonly)
12480         {
12481                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12482                 for (j = 0;j < numsurfacelist;j++)
12483                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12484         }
12485
12486         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12487 }
12488
12489 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12490 {
12491         int i, j, endj, flagsmask;
12492         dp_model_t *model = ent->model;
12493         msurface_t *surfaces;
12494         unsigned char *update;
12495         int numsurfacelist = 0;
12496         if (model == NULL)
12497                 return;
12498
12499         if (r_maxsurfacelist < model->num_surfaces)
12500         {
12501                 r_maxsurfacelist = model->num_surfaces;
12502                 if (r_surfacelist)
12503                         Mem_Free((msurface_t **)r_surfacelist);
12504                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12505         }
12506
12507         // if the model is static it doesn't matter what value we give for
12508         // wantnormals and wanttangents, so this logic uses only rules applicable
12509         // to a model, knowing that they are meaningless otherwise
12510         if (ent == r_refdef.scene.worldentity)
12511                 RSurf_ActiveWorldEntity();
12512         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12513                 RSurf_ActiveModelEntity(ent, false, false, false);
12514         else if (prepass)
12515                 RSurf_ActiveModelEntity(ent, true, true, true);
12516         else if (depthonly)
12517         {
12518                 switch (vid.renderpath)
12519                 {
12520                 case RENDERPATH_GL20:
12521                 case RENDERPATH_D3D9:
12522                 case RENDERPATH_D3D10:
12523                 case RENDERPATH_D3D11:
12524                 case RENDERPATH_SOFT:
12525                 case RENDERPATH_GLES2:
12526                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12527                         break;
12528                 case RENDERPATH_GL11:
12529                 case RENDERPATH_GL13:
12530                 case RENDERPATH_GLES1:
12531                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12532                         break;
12533                 }
12534         }
12535         else
12536         {
12537                 switch (vid.renderpath)
12538                 {
12539                 case RENDERPATH_GL20:
12540                 case RENDERPATH_D3D9:
12541                 case RENDERPATH_D3D10:
12542                 case RENDERPATH_D3D11:
12543                 case RENDERPATH_SOFT:
12544                 case RENDERPATH_GLES2:
12545                         RSurf_ActiveModelEntity(ent, true, true, false);
12546                         break;
12547                 case RENDERPATH_GL11:
12548                 case RENDERPATH_GL13:
12549                 case RENDERPATH_GLES1:
12550                         RSurf_ActiveModelEntity(ent, true, false, false);
12551                         break;
12552                 }
12553         }
12554
12555         surfaces = model->data_surfaces;
12556         update = model->brushq1.lightmapupdateflags;
12557
12558         // update light styles
12559         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12560         {
12561                 model_brush_lightstyleinfo_t *style;
12562                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12563                 {
12564                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12565                         {
12566                                 int *list = style->surfacelist;
12567                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12568                                 for (j = 0;j < style->numsurfaces;j++)
12569                                         update[list[j]] = true;
12570                         }
12571                 }
12572         }
12573
12574         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12575
12576         if (debug)
12577         {
12578                 R_DrawDebugModel();
12579                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12580                 return;
12581         }
12582
12583         rsurface.lightmaptexture = NULL;
12584         rsurface.deluxemaptexture = NULL;
12585         rsurface.uselightmaptexture = false;
12586         rsurface.texture = NULL;
12587         rsurface.rtlight = NULL;
12588         numsurfacelist = 0;
12589         // add visible surfaces to draw list
12590         for (i = 0;i < model->nummodelsurfaces;i++)
12591                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12592         // don't do anything if there were no surfaces
12593         if (!numsurfacelist)
12594         {
12595                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12596                 return;
12597         }
12598         // update lightmaps if needed
12599         if (update)
12600         {
12601                 int updated = 0;
12602                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12603                 {
12604                         if (update[j])
12605                         {
12606                                 updated++;
12607                                 R_BuildLightMap(ent, surfaces + j);
12608                         }
12609                 }
12610         }
12611
12612         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12613
12614         // add to stats if desired
12615         if (r_speeds.integer && !skysurfaces && !depthonly)
12616         {
12617                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12618                 for (j = 0;j < numsurfacelist;j++)
12619                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12620         }
12621
12622         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12623 }
12624
12625 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12626 {
12627         static texture_t texture;
12628         static msurface_t surface;
12629         const msurface_t *surfacelist = &surface;
12630
12631         // fake enough texture and surface state to render this geometry
12632
12633         texture.update_lastrenderframe = -1; // regenerate this texture
12634         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12635         texture.currentskinframe = skinframe;
12636         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12637         texture.offsetmapping = OFFSETMAPPING_OFF;
12638         texture.offsetscale = 1;
12639         texture.specularscalemod = 1;
12640         texture.specularpowermod = 1;
12641         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12642         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12643         // JUST GREP FOR "specularscalemod = 1".
12644
12645         surface.texture = &texture;
12646         surface.num_triangles = numtriangles;
12647         surface.num_firsttriangle = firsttriangle;
12648         surface.num_vertices = numvertices;
12649         surface.num_firstvertex = firstvertex;
12650
12651         // now render it
12652         rsurface.texture = R_GetCurrentTexture(surface.texture);
12653         rsurface.lightmaptexture = NULL;
12654         rsurface.deluxemaptexture = NULL;
12655         rsurface.uselightmaptexture = false;
12656         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12657 }
12658
12659 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)
12660 {
12661         static msurface_t surface;
12662         const msurface_t *surfacelist = &surface;
12663
12664         // fake enough texture and surface state to render this geometry
12665         surface.texture = texture;
12666         surface.num_triangles = numtriangles;
12667         surface.num_firsttriangle = firsttriangle;
12668         surface.num_vertices = numvertices;
12669         surface.num_firstvertex = firstvertex;
12670
12671         // now render it
12672         rsurface.texture = R_GetCurrentTexture(surface.texture);
12673         rsurface.lightmaptexture = NULL;
12674         rsurface.deluxemaptexture = NULL;
12675         rsurface.uselightmaptexture = false;
12676         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12677 }