]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
140da814da77c82e821e1a52448a469e9d56a3d5
[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 }
1378
1379 #ifdef SUPPORTD3D
1380
1381 #ifdef SUPPORTD3D
1382 #include <d3d9.h>
1383 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1384 extern D3DCAPS9 vid_d3d9caps;
1385 #endif
1386
1387 struct r_hlsl_permutation_s;
1388 typedef struct r_hlsl_permutation_s
1389 {
1390         /// hash lookup data
1391         struct r_hlsl_permutation_s *hashnext;
1392         unsigned int mode;
1393         unsigned int permutation;
1394
1395         /// indicates if we have tried compiling this permutation already
1396         qboolean compiled;
1397         /// NULL if compilation failed
1398         IDirect3DVertexShader9 *vertexshader;
1399         IDirect3DPixelShader9 *pixelshader;
1400 }
1401 r_hlsl_permutation_t;
1402
1403 typedef enum D3DVSREGISTER_e
1404 {
1405         D3DVSREGISTER_TexMatrix = 0, // float4x4
1406         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1407         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1408         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1409         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1410         D3DVSREGISTER_ModelToLight = 20, // float4x4
1411         D3DVSREGISTER_EyePosition = 24,
1412         D3DVSREGISTER_FogPlane = 25,
1413         D3DVSREGISTER_LightDir = 26,
1414         D3DVSREGISTER_LightPosition = 27,
1415 }
1416 D3DVSREGISTER_t;
1417
1418 typedef enum D3DPSREGISTER_e
1419 {
1420         D3DPSREGISTER_Alpha = 0,
1421         D3DPSREGISTER_BloomBlur_Parameters = 1,
1422         D3DPSREGISTER_ClientTime = 2,
1423         D3DPSREGISTER_Color_Ambient = 3,
1424         D3DPSREGISTER_Color_Diffuse = 4,
1425         D3DPSREGISTER_Color_Specular = 5,
1426         D3DPSREGISTER_Color_Glow = 6,
1427         D3DPSREGISTER_Color_Pants = 7,
1428         D3DPSREGISTER_Color_Shirt = 8,
1429         D3DPSREGISTER_DeferredColor_Ambient = 9,
1430         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1431         D3DPSREGISTER_DeferredColor_Specular = 11,
1432         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1433         D3DPSREGISTER_DeferredMod_Specular = 13,
1434         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1435         D3DPSREGISTER_EyePosition = 15, // unused
1436         D3DPSREGISTER_FogColor = 16,
1437         D3DPSREGISTER_FogHeightFade = 17,
1438         D3DPSREGISTER_FogPlane = 18,
1439         D3DPSREGISTER_FogPlaneViewDist = 19,
1440         D3DPSREGISTER_FogRangeRecip = 20,
1441         D3DPSREGISTER_LightColor = 21,
1442         D3DPSREGISTER_LightDir = 22, // unused
1443         D3DPSREGISTER_LightPosition = 23,
1444         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1445         D3DPSREGISTER_PixelSize = 25,
1446         D3DPSREGISTER_ReflectColor = 26,
1447         D3DPSREGISTER_ReflectFactor = 27,
1448         D3DPSREGISTER_ReflectOffset = 28,
1449         D3DPSREGISTER_RefractColor = 29,
1450         D3DPSREGISTER_Saturation = 30,
1451         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1452         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1453         D3DPSREGISTER_ScreenToDepth = 33,
1454         D3DPSREGISTER_ShadowMap_Parameters = 34,
1455         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1456         D3DPSREGISTER_SpecularPower = 36,
1457         D3DPSREGISTER_UserVec1 = 37,
1458         D3DPSREGISTER_UserVec2 = 38,
1459         D3DPSREGISTER_UserVec3 = 39,
1460         D3DPSREGISTER_UserVec4 = 40,
1461         D3DPSREGISTER_ViewTintColor = 41,
1462         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1463         D3DPSREGISTER_BloomColorSubtract = 43,
1464         D3DPSREGISTER_ViewToLight = 44, // float4x4
1465         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1466         D3DPSREGISTER_NormalmapScrollBlend = 52,
1467         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1468         D3DPSREGISTER_OffsetMapping_Bias = 54,
1469         // next at 54
1470 }
1471 D3DPSREGISTER_t;
1472
1473 /// information about each possible shader permutation
1474 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1475 /// currently selected permutation
1476 r_hlsl_permutation_t *r_hlsl_permutation;
1477 /// storage for permutations linked in the hash table
1478 memexpandablearray_t r_hlsl_permutationarray;
1479
1480 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1481 {
1482         //unsigned int hashdepth = 0;
1483         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1484         r_hlsl_permutation_t *p;
1485         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1486         {
1487                 if (p->mode == mode && p->permutation == permutation)
1488                 {
1489                         //if (hashdepth > 10)
1490                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1491                         return p;
1492                 }
1493                 //hashdepth++;
1494         }
1495         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1496         p->mode = mode;
1497         p->permutation = permutation;
1498         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1499         r_hlsl_permutationhash[mode][hashindex] = p;
1500         //if (hashdepth > 10)
1501         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1502         return p;
1503 }
1504
1505 #include <d3dx9.h>
1506 //#include <d3dx9shader.h>
1507 //#include <d3dx9mesh.h>
1508
1509 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1510 {
1511         DWORD *vsbin = NULL;
1512         DWORD *psbin = NULL;
1513         fs_offset_t vsbinsize;
1514         fs_offset_t psbinsize;
1515 //      IDirect3DVertexShader9 *vs = NULL;
1516 //      IDirect3DPixelShader9 *ps = NULL;
1517         ID3DXBuffer *vslog = NULL;
1518         ID3DXBuffer *vsbuffer = NULL;
1519         ID3DXConstantTable *vsconstanttable = NULL;
1520         ID3DXBuffer *pslog = NULL;
1521         ID3DXBuffer *psbuffer = NULL;
1522         ID3DXConstantTable *psconstanttable = NULL;
1523         int vsresult = 0;
1524         int psresult = 0;
1525         char temp[MAX_INPUTLINE];
1526         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1527         char vabuf[1024];
1528         qboolean debugshader = gl_paranoid.integer != 0;
1529         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1530         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1531         if (!debugshader)
1532         {
1533                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1534                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1535         }
1536         if ((!vsbin && vertstring) || (!psbin && fragstring))
1537         {
1538                 const char* dllnames_d3dx9 [] =
1539                 {
1540                         "d3dx9_43.dll",
1541                         "d3dx9_42.dll",
1542                         "d3dx9_41.dll",
1543                         "d3dx9_40.dll",
1544                         "d3dx9_39.dll",
1545                         "d3dx9_38.dll",
1546                         "d3dx9_37.dll",
1547                         "d3dx9_36.dll",
1548                         "d3dx9_35.dll",
1549                         "d3dx9_34.dll",
1550                         "d3dx9_33.dll",
1551                         "d3dx9_32.dll",
1552                         "d3dx9_31.dll",
1553                         "d3dx9_30.dll",
1554                         "d3dx9_29.dll",
1555                         "d3dx9_28.dll",
1556                         "d3dx9_27.dll",
1557                         "d3dx9_26.dll",
1558                         "d3dx9_25.dll",
1559                         "d3dx9_24.dll",
1560                         NULL
1561                 };
1562                 dllhandle_t d3dx9_dll = NULL;
1563                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1564                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1565                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1566                 dllfunction_t d3dx9_dllfuncs[] =
1567                 {
1568                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1569                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1570                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1571                         {NULL, NULL}
1572                 };
1573                 // LordHavoc: the June 2010 SDK lacks these macros to make ID3DXBuffer usable in C, and to make it work in both C and C++ the macros are needed...
1574 #ifndef ID3DXBuffer_GetBufferPointer
1575 #if !defined(__cplusplus) || defined(CINTERFACE)
1576 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1577 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1578 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1579 #else
1580 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1581 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1582 #define ID3DXBuffer_Release(p)            (p)->Release()
1583 #endif
1584 #endif
1585                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1586                 {
1587                         DWORD shaderflags = 0;
1588                         if (debugshader)
1589                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1590                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1591                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1592                         if (vertstring && vertstring[0])
1593                         {
1594                                 if (debugshader)
1595                                 {
1596                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1597                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1598                                 }
1599                                 else
1600                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1601                                 if (vsbuffer)
1602                                 {
1603                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1604                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1605                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1606                                         ID3DXBuffer_Release(vsbuffer);
1607                                 }
1608                                 if (vslog)
1609                                 {
1610                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1611                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1612                                         ID3DXBuffer_Release(vslog);
1613                                 }
1614                         }
1615                         if (fragstring && fragstring[0])
1616                         {
1617                                 if (debugshader)
1618                                 {
1619                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1620                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1621                                 }
1622                                 else
1623                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1624                                 if (psbuffer)
1625                                 {
1626                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1627                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1628                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1629                                         ID3DXBuffer_Release(psbuffer);
1630                                 }
1631                                 if (pslog)
1632                                 {
1633                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1634                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1635                                         ID3DXBuffer_Release(pslog);
1636                                 }
1637                         }
1638                         Sys_UnloadLibrary(&d3dx9_dll);
1639                 }
1640                 else
1641                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1642         }
1643         if (vsbin && psbin)
1644         {
1645                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1646                 if (FAILED(vsresult))
1647                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1648                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1649                 if (FAILED(psresult))
1650                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1651         }
1652         // free the shader data
1653         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1654         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1655 }
1656
1657 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1658 {
1659         int i;
1660         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1661         int vertstring_length = 0;
1662         int geomstring_length = 0;
1663         int fragstring_length = 0;
1664         char *t;
1665         char *sourcestring;
1666         char *vertstring, *geomstring, *fragstring;
1667         char permutationname[256];
1668         char cachename[256];
1669         int vertstrings_count = 0;
1670         int geomstrings_count = 0;
1671         int fragstrings_count = 0;
1672         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1673         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1674         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1675
1676         if (p->compiled)
1677                 return;
1678         p->compiled = true;
1679         p->vertexshader = NULL;
1680         p->pixelshader = NULL;
1681
1682         permutationname[0] = 0;
1683         cachename[0] = 0;
1684         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1685
1686         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1687         strlcat(cachename, "hlsl/", sizeof(cachename));
1688
1689         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1690         vertstrings_count = 0;
1691         geomstrings_count = 0;
1692         fragstrings_count = 0;
1693         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1694         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1695         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1696
1697         // the first pretext is which type of shader to compile as
1698         // (later these will all be bound together as a program object)
1699         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1700         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1701         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1702
1703         // the second pretext is the mode (for example a light source)
1704         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1705         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1706         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1707         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1708         strlcat(cachename, modeinfo->name, sizeof(cachename));
1709
1710         // now add all the permutation pretexts
1711         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1712         {
1713                 if (permutation & (1<<i))
1714                 {
1715                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1716                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1717                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1718                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1719                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1720                 }
1721                 else
1722                 {
1723                         // keep line numbers correct
1724                         vertstrings_list[vertstrings_count++] = "\n";
1725                         geomstrings_list[geomstrings_count++] = "\n";
1726                         fragstrings_list[fragstrings_count++] = "\n";
1727                 }
1728         }
1729
1730         // add static parms
1731         R_CompileShader_AddStaticParms(mode, permutation);
1732         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1733         vertstrings_count += shaderstaticparms_count;
1734         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1735         geomstrings_count += shaderstaticparms_count;
1736         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1737         fragstrings_count += shaderstaticparms_count;
1738
1739         // replace spaces in the cachename with _ characters
1740         for (i = 0;cachename[i];i++)
1741                 if (cachename[i] == ' ')
1742                         cachename[i] = '_';
1743
1744         // now append the shader text itself
1745         vertstrings_list[vertstrings_count++] = sourcestring;
1746         geomstrings_list[geomstrings_count++] = sourcestring;
1747         fragstrings_list[fragstrings_count++] = sourcestring;
1748
1749         vertstring_length = 0;
1750         for (i = 0;i < vertstrings_count;i++)
1751                 vertstring_length += strlen(vertstrings_list[i]);
1752         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1753         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1754                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1755
1756         geomstring_length = 0;
1757         for (i = 0;i < geomstrings_count;i++)
1758                 geomstring_length += strlen(geomstrings_list[i]);
1759         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1760         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1761                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1762
1763         fragstring_length = 0;
1764         for (i = 0;i < fragstrings_count;i++)
1765                 fragstring_length += strlen(fragstrings_list[i]);
1766         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1767         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1768                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1769
1770         // try to load the cached shader, or generate one
1771         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1772
1773         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1774                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1775         else
1776                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1777
1778         // free the strings
1779         if (vertstring)
1780                 Mem_Free(vertstring);
1781         if (geomstring)
1782                 Mem_Free(geomstring);
1783         if (fragstring)
1784                 Mem_Free(fragstring);
1785         if (sourcestring)
1786                 Mem_Free(sourcestring);
1787 }
1788
1789 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1790 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1791 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1792 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1793 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1794 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1795
1796 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1797 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1798 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1799 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1800 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1801 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1802
1803 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1804 {
1805         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1806         if (r_hlsl_permutation != perm)
1807         {
1808                 r_hlsl_permutation = perm;
1809                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1810                 {
1811                         if (!r_hlsl_permutation->compiled)
1812                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1813                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1814                         {
1815                                 // remove features until we find a valid permutation
1816                                 int i;
1817                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1818                                 {
1819                                         // reduce i more quickly whenever it would not remove any bits
1820                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1821                                         if (!(permutation & j))
1822                                                 continue;
1823                                         permutation -= j;
1824                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1825                                         if (!r_hlsl_permutation->compiled)
1826                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1827                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1828                                                 break;
1829                                 }
1830                                 if (i >= SHADERPERMUTATION_COUNT)
1831                                 {
1832                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1833                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1834                                         return; // no bit left to clear, entire mode is broken
1835                                 }
1836                         }
1837                 }
1838                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1839                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1840         }
1841         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1842         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1843         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1844 }
1845 #endif
1846
1847 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1848 {
1849         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1850         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1851         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1852         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1853 }
1854
1855 void R_GLSL_Restart_f(void)
1856 {
1857         unsigned int i, limit;
1858         if (glslshaderstring)
1859                 Mem_Free(glslshaderstring);
1860         glslshaderstring = NULL;
1861         if (hlslshaderstring)
1862                 Mem_Free(hlslshaderstring);
1863         hlslshaderstring = NULL;
1864         switch(vid.renderpath)
1865         {
1866         case RENDERPATH_D3D9:
1867 #ifdef SUPPORTD3D
1868                 {
1869                         r_hlsl_permutation_t *p;
1870                         r_hlsl_permutation = NULL;
1871                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1872                         for (i = 0;i < limit;i++)
1873                         {
1874                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1875                                 {
1876                                         if (p->vertexshader)
1877                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1878                                         if (p->pixelshader)
1879                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1880                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1881                                 }
1882                         }
1883                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1884                 }
1885 #endif
1886                 break;
1887         case RENDERPATH_D3D10:
1888                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1889                 break;
1890         case RENDERPATH_D3D11:
1891                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1892                 break;
1893         case RENDERPATH_GL20:
1894         case RENDERPATH_GLES2:
1895                 {
1896                         r_glsl_permutation_t *p;
1897                         r_glsl_permutation = NULL;
1898                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1899                         for (i = 0;i < limit;i++)
1900                         {
1901                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1902                                 {
1903                                         GL_Backend_FreeProgram(p->program);
1904                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1905                                 }
1906                         }
1907                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1908                 }
1909                 break;
1910         case RENDERPATH_GL11:
1911         case RENDERPATH_GL13:
1912         case RENDERPATH_GLES1:
1913                 break;
1914         case RENDERPATH_SOFT:
1915                 break;
1916         }
1917 }
1918
1919 static void R_GLSL_DumpShader_f(void)
1920 {
1921         int i, language, mode, dupe;
1922         char *text;
1923         shadermodeinfo_t *modeinfo;
1924         qfile_t *file;
1925
1926         for (language = 0;language < 2;language++)
1927         {
1928                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1929                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1930                 {
1931                         // don't dump the same file multiple times (most or all shaders come from the same file)
1932                         for (dupe = mode - 1;dupe >= 0;dupe--)
1933                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1934                                         break;
1935                         if (dupe >= 0)
1936                                 continue;
1937                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1938                         if (!text)
1939                                 continue;
1940                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1941                         if (file)
1942                         {
1943                                 FS_Print(file, "/* The engine may define the following macros:\n");
1944                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1945                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1946                                         FS_Print(file, modeinfo[i].pretext);
1947                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1948                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1949                                 FS_Print(file, "*/\n");
1950                                 FS_Print(file, text);
1951                                 FS_Close(file);
1952                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1953                         }
1954                         else
1955                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1956                         Mem_Free(text);
1957                 }
1958         }
1959 }
1960
1961 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1962 {
1963         unsigned int permutation = 0;
1964         if (r_trippy.integer && !notrippy)
1965                 permutation |= SHADERPERMUTATION_TRIPPY;
1966         permutation |= SHADERPERMUTATION_VIEWTINT;
1967         if (first)
1968                 permutation |= SHADERPERMUTATION_DIFFUSE;
1969         if (second)
1970                 permutation |= SHADERPERMUTATION_SPECULAR;
1971         if (texturemode == GL_MODULATE)
1972                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1973         else if (texturemode == GL_ADD)
1974                 permutation |= SHADERPERMUTATION_GLOW;
1975         else if (texturemode == GL_DECAL)
1976                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1977         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1978                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1979         if (suppresstexalpha)
1980                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1981         if (!second)
1982                 texturemode = GL_MODULATE;
1983         if (vid.allowalphatocoverage)
1984                 GL_AlphaToCoverage(false);
1985         switch (vid.renderpath)
1986         {
1987         case RENDERPATH_D3D9:
1988 #ifdef SUPPORTD3D
1989                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1990                 R_Mesh_TexBind(GL20TU_FIRST , first );
1991                 R_Mesh_TexBind(GL20TU_SECOND, second);
1992                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1993                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1994 #endif
1995                 break;
1996         case RENDERPATH_D3D10:
1997                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1998                 break;
1999         case RENDERPATH_D3D11:
2000                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2001                 break;
2002         case RENDERPATH_GL20:
2003         case RENDERPATH_GLES2:
2004                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2005                 if (r_glsl_permutation->tex_Texture_First >= 0)
2006                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2007                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2008                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2009                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2010                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2011                 break;
2012         case RENDERPATH_GL13:
2013         case RENDERPATH_GLES1:
2014                 R_Mesh_TexBind(0, first );
2015                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2016                 R_Mesh_TexMatrix(0, NULL);
2017                 R_Mesh_TexBind(1, second);
2018                 if (second)
2019                 {
2020                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2021                         R_Mesh_TexMatrix(1, NULL);
2022                 }
2023                 break;
2024         case RENDERPATH_GL11:
2025                 R_Mesh_TexBind(0, first );
2026                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2027                 R_Mesh_TexMatrix(0, NULL);
2028                 break;
2029         case RENDERPATH_SOFT:
2030                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2031                 R_Mesh_TexBind(GL20TU_FIRST , first );
2032                 R_Mesh_TexBind(GL20TU_SECOND, second);
2033                 break;
2034         }
2035 }
2036
2037 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2038 {
2039         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2040 }
2041
2042 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2043 {
2044         unsigned int permutation = 0;
2045         if (r_trippy.integer && !notrippy)
2046                 permutation |= SHADERPERMUTATION_TRIPPY;
2047         if (depthrgb)
2048                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2049         if (skeletal)
2050                 permutation |= SHADERPERMUTATION_SKELETAL;
2051
2052         if (vid.allowalphatocoverage)
2053                 GL_AlphaToCoverage(false);
2054         switch (vid.renderpath)
2055         {
2056         case RENDERPATH_D3D9:
2057 #ifdef SUPPORTD3D
2058                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2059 #endif
2060                 break;
2061         case RENDERPATH_D3D10:
2062                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2063                 break;
2064         case RENDERPATH_D3D11:
2065                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2066                 break;
2067         case RENDERPATH_GL20:
2068         case RENDERPATH_GLES2:
2069                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2070                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2071                 break;
2072         case RENDERPATH_GL13:
2073         case RENDERPATH_GLES1:
2074                 R_Mesh_TexBind(0, 0);
2075                 R_Mesh_TexBind(1, 0);
2076                 break;
2077         case RENDERPATH_GL11:
2078                 R_Mesh_TexBind(0, 0);
2079                 break;
2080         case RENDERPATH_SOFT:
2081                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2082                 break;
2083         }
2084 }
2085
2086 extern qboolean r_shadow_usingdeferredprepass;
2087 extern rtexture_t *r_shadow_attenuationgradienttexture;
2088 extern rtexture_t *r_shadow_attenuation2dtexture;
2089 extern rtexture_t *r_shadow_attenuation3dtexture;
2090 extern qboolean r_shadow_usingshadowmap2d;
2091 extern qboolean r_shadow_usingshadowmaportho;
2092 extern float r_shadow_shadowmap_texturescale[2];
2093 extern float r_shadow_shadowmap_parameters[4];
2094 extern qboolean r_shadow_shadowmapvsdct;
2095 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2096 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2097 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2098 extern matrix4x4_t r_shadow_shadowmapmatrix;
2099 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2100 extern int r_shadow_prepass_width;
2101 extern int r_shadow_prepass_height;
2102 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2103 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2104 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2105 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2106
2107 #define BLENDFUNC_ALLOWS_COLORMOD      1
2108 #define BLENDFUNC_ALLOWS_FOG           2
2109 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2110 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2111 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2112 static int R_BlendFuncFlags(int src, int dst)
2113 {
2114         int r = 0;
2115
2116         // a blendfunc allows colormod if:
2117         // a) it can never keep the destination pixel invariant, or
2118         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2119         // this is to prevent unintended side effects from colormod
2120
2121         // a blendfunc allows fog if:
2122         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2123         // this is to prevent unintended side effects from fog
2124
2125         // these checks are the output of fogeval.pl
2126
2127         r |= BLENDFUNC_ALLOWS_COLORMOD;
2128         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2129         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2130         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2131         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2132         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2133         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2134         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2135         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2136         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2137         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2138         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2139         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2140         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2141         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2142         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2143         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2144         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2145         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2146         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2147         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2148         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2149
2150         return r;
2151 }
2152
2153 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2154 {
2155         // select a permutation of the lighting shader appropriate to this
2156         // combination of texture, entity, light source, and fogging, only use the
2157         // minimum features necessary to avoid wasting rendering time in the
2158         // fragment shader on features that are not being used
2159         unsigned int permutation = 0;
2160         unsigned int mode = 0;
2161         int blendfuncflags;
2162         static float dummy_colormod[3] = {1, 1, 1};
2163         float *colormod = rsurface.colormod;
2164         float m16f[16];
2165         matrix4x4_t tempmatrix;
2166         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2167         if (r_trippy.integer && !notrippy)
2168                 permutation |= SHADERPERMUTATION_TRIPPY;
2169         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2170                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2171         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2172                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2173         if (rsurfacepass == RSURFPASS_BACKGROUND)
2174         {
2175                 // distorted background
2176                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2177                 {
2178                         mode = SHADERMODE_WATER;
2179                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2180                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2181                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2182                         {
2183                                 // this is the right thing to do for wateralpha
2184                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2185                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2186                         }
2187                         else
2188                         {
2189                                 // this is the right thing to do for entity alpha
2190                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2191                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2192                         }
2193                 }
2194                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2195                 {
2196                         mode = SHADERMODE_REFRACTION;
2197                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2198                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2199                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2200                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2201                 }
2202                 else
2203                 {
2204                         mode = SHADERMODE_GENERIC;
2205                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2206                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2207                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2208                 }
2209                 if (vid.allowalphatocoverage)
2210                         GL_AlphaToCoverage(false);
2211         }
2212         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2213         {
2214                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2215                 {
2216                         switch(rsurface.texture->offsetmapping)
2217                         {
2218                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2219                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2220                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2221                         case OFFSETMAPPING_OFF: break;
2222                         }
2223                 }
2224                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2225                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2226                 // normalmap (deferred prepass), may use alpha test on diffuse
2227                 mode = SHADERMODE_DEFERREDGEOMETRY;
2228                 GL_BlendFunc(GL_ONE, GL_ZERO);
2229                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2230                 if (vid.allowalphatocoverage)
2231                         GL_AlphaToCoverage(false);
2232         }
2233         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2234         {
2235                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2236                 {
2237                         switch(rsurface.texture->offsetmapping)
2238                         {
2239                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2240                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2241                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2242                         case OFFSETMAPPING_OFF: break;
2243                         }
2244                 }
2245                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2246                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2247                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2248                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2249                 // light source
2250                 mode = SHADERMODE_LIGHTSOURCE;
2251                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2252                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2253                 if (diffusescale > 0)
2254                         permutation |= SHADERPERMUTATION_DIFFUSE;
2255                 if (specularscale > 0)
2256                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2257                 if (r_refdef.fogenabled)
2258                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2259                 if (rsurface.texture->colormapping)
2260                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2261                 if (r_shadow_usingshadowmap2d)
2262                 {
2263                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2264                         if(r_shadow_shadowmapvsdct)
2265                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2266
2267                         if (r_shadow_shadowmap2ddepthbuffer)
2268                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2269                 }
2270                 if (rsurface.texture->reflectmasktexture)
2271                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2272                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2273                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2274                 if (vid.allowalphatocoverage)
2275                         GL_AlphaToCoverage(false);
2276         }
2277         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2278         {
2279                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2280                 {
2281                         switch(rsurface.texture->offsetmapping)
2282                         {
2283                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2284                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286                         case OFFSETMAPPING_OFF: break;
2287                         }
2288                 }
2289                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2290                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2291                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2292                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2293                 // unshaded geometry (fullbright or ambient model lighting)
2294                 mode = SHADERMODE_FLATCOLOR;
2295                 ambientscale = diffusescale = specularscale = 0;
2296                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2297                         permutation |= SHADERPERMUTATION_GLOW;
2298                 if (r_refdef.fogenabled)
2299                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2300                 if (rsurface.texture->colormapping)
2301                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2302                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2303                 {
2304                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2305                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2306
2307                         if (r_shadow_shadowmap2ddepthbuffer)
2308                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2309                 }
2310                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2311                         permutation |= SHADERPERMUTATION_REFLECTION;
2312                 if (rsurface.texture->reflectmasktexture)
2313                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2314                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2315                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2316                 // when using alphatocoverage, we don't need alphakill
2317                 if (vid.allowalphatocoverage)
2318                 {
2319                         if (r_transparent_alphatocoverage.integer)
2320                         {
2321                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2322                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2323                         }
2324                         else
2325                                 GL_AlphaToCoverage(false);
2326                 }
2327         }
2328         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2329         {
2330                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2331                 {
2332                         switch(rsurface.texture->offsetmapping)
2333                         {
2334                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2335                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2336                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2337                         case OFFSETMAPPING_OFF: break;
2338                         }
2339                 }
2340                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2341                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2342                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2343                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2344                 // directional model lighting
2345                 mode = SHADERMODE_LIGHTDIRECTION;
2346                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2347                         permutation |= SHADERPERMUTATION_GLOW;
2348                 permutation |= SHADERPERMUTATION_DIFFUSE;
2349                 if (specularscale > 0)
2350                         permutation |= SHADERPERMUTATION_SPECULAR;
2351                 if (r_refdef.fogenabled)
2352                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2353                 if (rsurface.texture->colormapping)
2354                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2355                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2356                 {
2357                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2358                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2359
2360                         if (r_shadow_shadowmap2ddepthbuffer)
2361                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2362                 }
2363                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2364                         permutation |= SHADERPERMUTATION_REFLECTION;
2365                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2366                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2367                 if (rsurface.texture->reflectmasktexture)
2368                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2369                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2370                 {
2371                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2372                         if (r_shadow_bouncegriddirectional)
2373                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2374                 }
2375                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2376                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2377                 // when using alphatocoverage, we don't need alphakill
2378                 if (vid.allowalphatocoverage)
2379                 {
2380                         if (r_transparent_alphatocoverage.integer)
2381                         {
2382                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2383                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2384                         }
2385                         else
2386                                 GL_AlphaToCoverage(false);
2387                 }
2388         }
2389         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2390         {
2391                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2392                 {
2393                         switch(rsurface.texture->offsetmapping)
2394                         {
2395                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2396                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2397                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2398                         case OFFSETMAPPING_OFF: break;
2399                         }
2400                 }
2401                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2402                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2403                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2404                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2405                 // ambient model lighting
2406                 mode = SHADERMODE_LIGHTDIRECTION;
2407                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2408                         permutation |= SHADERPERMUTATION_GLOW;
2409                 if (r_refdef.fogenabled)
2410                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2411                 if (rsurface.texture->colormapping)
2412                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2413                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2414                 {
2415                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2416                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2417
2418                         if (r_shadow_shadowmap2ddepthbuffer)
2419                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2420                 }
2421                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2422                         permutation |= SHADERPERMUTATION_REFLECTION;
2423                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2424                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2425                 if (rsurface.texture->reflectmasktexture)
2426                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2427                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2428                 {
2429                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2430                         if (r_shadow_bouncegriddirectional)
2431                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2432                 }
2433                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2434                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2435                 // when using alphatocoverage, we don't need alphakill
2436                 if (vid.allowalphatocoverage)
2437                 {
2438                         if (r_transparent_alphatocoverage.integer)
2439                         {
2440                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2441                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2442                         }
2443                         else
2444                                 GL_AlphaToCoverage(false);
2445                 }
2446         }
2447         else
2448         {
2449                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2450                 {
2451                         switch(rsurface.texture->offsetmapping)
2452                         {
2453                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2454                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2455                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2456                         case OFFSETMAPPING_OFF: break;
2457                         }
2458                 }
2459                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2460                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2461                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2462                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2463                 // lightmapped wall
2464                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2465                         permutation |= SHADERPERMUTATION_GLOW;
2466                 if (r_refdef.fogenabled)
2467                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2468                 if (rsurface.texture->colormapping)
2469                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2470                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2471                 {
2472                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2473                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2474
2475                         if (r_shadow_shadowmap2ddepthbuffer)
2476                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2477                 }
2478                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2479                         permutation |= SHADERPERMUTATION_REFLECTION;
2480                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2481                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2482                 if (rsurface.texture->reflectmasktexture)
2483                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2484                 if (FAKELIGHT_ENABLED)
2485                 {
2486                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2487                         mode = SHADERMODE_FAKELIGHT;
2488                         permutation |= SHADERPERMUTATION_DIFFUSE;
2489                         if (specularscale > 0)
2490                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2491                 }
2492                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2493                 {
2494                         // deluxemapping (light direction texture)
2495                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2496                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2497                         else
2498                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2499                         permutation |= SHADERPERMUTATION_DIFFUSE;
2500                         if (specularscale > 0)
2501                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2502                 }
2503                 else if (r_glsl_deluxemapping.integer >= 2)
2504                 {
2505                         // fake deluxemapping (uniform light direction in tangentspace)
2506                         if (rsurface.uselightmaptexture)
2507                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2508                         else
2509                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2510                         permutation |= SHADERPERMUTATION_DIFFUSE;
2511                         if (specularscale > 0)
2512                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2513                 }
2514                 else if (rsurface.uselightmaptexture)
2515                 {
2516                         // ordinary lightmapping (q1bsp, q3bsp)
2517                         mode = SHADERMODE_LIGHTMAP;
2518                 }
2519                 else
2520                 {
2521                         // ordinary vertex coloring (q3bsp)
2522                         mode = SHADERMODE_VERTEXCOLOR;
2523                 }
2524                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2525                 {
2526                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2527                         if (r_shadow_bouncegriddirectional)
2528                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2529                 }
2530                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2531                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2532                 // when using alphatocoverage, we don't need alphakill
2533                 if (vid.allowalphatocoverage)
2534                 {
2535                         if (r_transparent_alphatocoverage.integer)
2536                         {
2537                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2538                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2539                         }
2540                         else
2541                                 GL_AlphaToCoverage(false);
2542                 }
2543         }
2544         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2545                 colormod = dummy_colormod;
2546         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2547                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2548         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2549                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2550         switch(vid.renderpath)
2551         {
2552         case RENDERPATH_D3D9:
2553 #ifdef SUPPORTD3D
2554                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2555                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2556                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2557                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2558                 if (mode == SHADERMODE_LIGHTSOURCE)
2559                 {
2560                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2561                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2562                 }
2563                 else
2564                 {
2565                         if (mode == SHADERMODE_LIGHTDIRECTION)
2566                         {
2567                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2568                         }
2569                 }
2570                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2571                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2572                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2573                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2574                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2575
2576                 if (mode == SHADERMODE_LIGHTSOURCE)
2577                 {
2578                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2579                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2580                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2581                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2582                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2583
2584                         // additive passes are only darkened by fog, not tinted
2585                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2586                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2587                 }
2588                 else
2589                 {
2590                         if (mode == SHADERMODE_FLATCOLOR)
2591                         {
2592                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2593                         }
2594                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2595                         {
2596                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2597                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2598                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2599                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2600                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2601                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2602                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2603                         }
2604                         else
2605                         {
2606                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2607                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2608                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2609                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2610                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2611                         }
2612                         // additive passes are only darkened by fog, not tinted
2613                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2614                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2615                         else
2616                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2617                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2618                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2619                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2620                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2621                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2622                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2623                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2624                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2625                         if (mode == SHADERMODE_WATER)
2626                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2627                 }
2628                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2629                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2630                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2631                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2632                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2633                 if (rsurface.texture->pantstexture)
2634                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2635                 else
2636                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2637                 if (rsurface.texture->shirttexture)
2638                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2639                 else
2640                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2641                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2642                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2643                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2644                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2645                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2646                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2647                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2648                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2649                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2650                         );
2651                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2652                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2653                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2654                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2655
2656                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2657                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2658                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2659                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2660                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2661                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2662                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2663                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2664                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2665                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2666                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2667                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2668                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2669                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2670                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2671                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2672                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2673                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2674                 {
2675                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2676                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2677                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2678                 }
2679                 else
2680                 {
2681                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2682                 }
2683 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2684                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2685                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2686                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2687                 {
2688                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2689                         if (rsurface.rtlight)
2690                         {
2691                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2692                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2693                         }
2694                 }
2695 #endif
2696                 break;
2697         case RENDERPATH_D3D10:
2698                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2699                 break;
2700         case RENDERPATH_D3D11:
2701                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2702                 break;
2703         case RENDERPATH_GL20:
2704         case RENDERPATH_GLES2:
2705                 if (!vid.useinterleavedarrays)
2706                 {
2707                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2708                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2709                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2710                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2711                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2712                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2713                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2714                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2715                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2716                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2717                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2718                 }
2719                 else
2720                 {
2721                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2722                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2723                 }
2724                 // this has to be after RSurf_PrepareVerticesForBatch
2725                 if (rsurface.batchskeletaltransform3x4buffer)
2726                         permutation |= SHADERPERMUTATION_SKELETAL;
2727                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2728                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2729                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2730                 if (mode == SHADERMODE_LIGHTSOURCE)
2731                 {
2732                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2733                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2734                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2735                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2736                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2737                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2738         
2739                         // additive passes are only darkened by fog, not tinted
2740                         if (r_glsl_permutation->loc_FogColor >= 0)
2741                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2742                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2743                 }
2744                 else
2745                 {
2746                         if (mode == SHADERMODE_FLATCOLOR)
2747                         {
2748                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2749                         }
2750                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2751                         {
2752                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2753                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2754                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2755                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2756                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2757                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2758                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2759                         }
2760                         else
2761                         {
2762                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2763                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2764                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2765                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2766                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2767                         }
2768                         // additive passes are only darkened by fog, not tinted
2769                         if (r_glsl_permutation->loc_FogColor >= 0)
2770                         {
2771                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2772                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2773                                 else
2774                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2775                         }
2776                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2777                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2778                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2779                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2780                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2781                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2782                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2783                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2784                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2785                 }
2786                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2787                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2788                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2789                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2790                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2791
2792                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2793                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2794                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2795                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2796                 {
2797                         if (rsurface.texture->pantstexture)
2798                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2799                         else
2800                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2801                 }
2802                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2803                 {
2804                         if (rsurface.texture->shirttexture)
2805                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2806                         else
2807                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2808                 }
2809                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2810                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2811                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2812                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2813                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2814                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2815                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2816                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2817                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2818                         );
2819                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2820                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2821                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2822                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2823                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2824                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2825
2826                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2827                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2828                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2829                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2830                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2831                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2832                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2833                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2834                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2835                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2836                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2837                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2838                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2839                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2840                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2841                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2842                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2843                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2844                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2845                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2846                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2847                 {
2848                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2849                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2850                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2851                 }
2852                 else
2853                 {
2854                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2855                 }
2856                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2857                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2858                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2859                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2860                 {
2861                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2862                         if (rsurface.rtlight)
2863                         {
2864                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2865                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2866                         }
2867                 }
2868                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2869                 CHECKGLERROR
2870                 break;
2871         case RENDERPATH_GL11:
2872         case RENDERPATH_GL13:
2873         case RENDERPATH_GLES1:
2874                 break;
2875         case RENDERPATH_SOFT:
2876                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2877                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2878                 R_SetupShader_SetPermutationSoft(mode, permutation);
2879                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2880                 if (mode == SHADERMODE_LIGHTSOURCE)
2881                 {
2882                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2883                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2884                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2885                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2886                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2887                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2888         
2889                         // additive passes are only darkened by fog, not tinted
2890                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2891                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2892                 }
2893                 else
2894                 {
2895                         if (mode == SHADERMODE_FLATCOLOR)
2896                         {
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2898                         }
2899                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2900                         {
2901                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2902                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2903                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2904                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2905                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2906                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2907                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2908                         }
2909                         else
2910                         {
2911                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2912                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2913                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2914                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2915                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2916                         }
2917                         // additive passes are only darkened by fog, not tinted
2918                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2919                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2920                         else
2921                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2922                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2923                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2924                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2925                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2926                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2927                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2928                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2929                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2930                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2931                 }
2932                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2933                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2934                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2935                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2936                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2937
2938                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2939                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2940                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2941                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2942                 {
2943                         if (rsurface.texture->pantstexture)
2944                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2945                         else
2946                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2947                 }
2948                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2949                 {
2950                         if (rsurface.texture->shirttexture)
2951                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2952                         else
2953                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2954                 }
2955                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2956                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2957                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2958                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2959                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2960                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2961                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2962                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2963                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2964                         );
2965                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2966                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2967                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2968                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2969
2970                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2971                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2972                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2973                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2974                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2975                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2976                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2977                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2978                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2979                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2980                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2981                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2982                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2983                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2984                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2985                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2986                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2987                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2988                 {
2989                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2990                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2991                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2992                 }
2993                 else
2994                 {
2995                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2996                 }
2997 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2998                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2999                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3000                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3001                 {
3002                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3003                         if (rsurface.rtlight)
3004                         {
3005                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3006                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3007                         }
3008                 }
3009                 break;
3010         }
3011 }
3012
3013 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3014 {
3015         // select a permutation of the lighting shader appropriate to this
3016         // combination of texture, entity, light source, and fogging, only use the
3017         // minimum features necessary to avoid wasting rendering time in the
3018         // fragment shader on features that are not being used
3019         unsigned int permutation = 0;
3020         unsigned int mode = 0;
3021         const float *lightcolorbase = rtlight->currentcolor;
3022         float ambientscale = rtlight->ambientscale;
3023         float diffusescale = rtlight->diffusescale;
3024         float specularscale = rtlight->specularscale;
3025         // this is the location of the light in view space
3026         vec3_t viewlightorigin;
3027         // this transforms from view space (camera) to light space (cubemap)
3028         matrix4x4_t viewtolight;
3029         matrix4x4_t lighttoview;
3030         float viewtolight16f[16];
3031         // light source
3032         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3033         if (rtlight->currentcubemap != r_texture_whitecube)
3034                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3035         if (diffusescale > 0)
3036                 permutation |= SHADERPERMUTATION_DIFFUSE;
3037         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3038                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3039         if (r_shadow_usingshadowmap2d)
3040         {
3041                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3042                 if (r_shadow_shadowmapvsdct)
3043                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3044
3045                 if (r_shadow_shadowmap2ddepthbuffer)
3046                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3047         }
3048         if (vid.allowalphatocoverage)
3049                 GL_AlphaToCoverage(false);
3050         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3051         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3052         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3053         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3054         switch(vid.renderpath)
3055         {
3056         case RENDERPATH_D3D9:
3057 #ifdef SUPPORTD3D
3058                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3059                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3060                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3061                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3062                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3063                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3064                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3065                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3066                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3067                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3068                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3069
3070                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3071                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3072                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3073                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3074                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3075 #endif
3076                 break;
3077         case RENDERPATH_D3D10:
3078                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3079                 break;
3080         case RENDERPATH_D3D11:
3081                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3082                 break;
3083         case RENDERPATH_GL20:
3084         case RENDERPATH_GLES2:
3085                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3086                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3087                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3088                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3089                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3090                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3091                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3092                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3093                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3094                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3095                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3096
3097                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3098                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3099                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3100                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3101                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3102                 break;
3103         case RENDERPATH_GL11:
3104         case RENDERPATH_GL13:
3105         case RENDERPATH_GLES1:
3106                 break;
3107         case RENDERPATH_SOFT:
3108                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3109                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3110                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3111                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3112                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3113                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3114                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3115                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3116                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3117                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3118                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3119
3120                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3121                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3122                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3123                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3124                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3125                 break;
3126         }
3127 }
3128
3129 #define SKINFRAME_HASH 1024
3130
3131 typedef struct
3132 {
3133         int loadsequence; // incremented each level change
3134         memexpandablearray_t array;
3135         skinframe_t *hash[SKINFRAME_HASH];
3136 }
3137 r_skinframe_t;
3138 r_skinframe_t r_skinframe;
3139
3140 void R_SkinFrame_PrepareForPurge(void)
3141 {
3142         r_skinframe.loadsequence++;
3143         // wrap it without hitting zero
3144         if (r_skinframe.loadsequence >= 200)
3145                 r_skinframe.loadsequence = 1;
3146 }
3147
3148 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3149 {
3150         if (!skinframe)
3151                 return;
3152         // mark the skinframe as used for the purging code
3153         skinframe->loadsequence = r_skinframe.loadsequence;
3154 }
3155
3156 void R_SkinFrame_Purge(void)
3157 {
3158         int i;
3159         skinframe_t *s;
3160         for (i = 0;i < SKINFRAME_HASH;i++)
3161         {
3162                 for (s = r_skinframe.hash[i];s;s = s->next)
3163                 {
3164                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3165                         {
3166                                 if (s->merged == s->base)
3167                                         s->merged = NULL;
3168                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3169                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3170                                 R_PurgeTexture(s->merged);s->merged = NULL;
3171                                 R_PurgeTexture(s->base  );s->base   = NULL;
3172                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3173                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3174                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3175                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3176                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3177                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3178                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3179                                 s->loadsequence = 0;
3180                         }
3181                 }
3182         }
3183 }
3184
3185 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3186         skinframe_t *item;
3187         char basename[MAX_QPATH];
3188
3189         Image_StripImageExtension(name, basename, sizeof(basename));
3190
3191         if( last == NULL ) {
3192                 int hashindex;
3193                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3194                 item = r_skinframe.hash[hashindex];
3195         } else {
3196                 item = last->next;
3197         }
3198
3199         // linearly search through the hash bucket
3200         for( ; item ; item = item->next ) {
3201                 if( !strcmp( item->basename, basename ) ) {
3202                         return item;
3203                 }
3204         }
3205         return NULL;
3206 }
3207
3208 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3209 {
3210         skinframe_t *item;
3211         int hashindex;
3212         char basename[MAX_QPATH];
3213
3214         Image_StripImageExtension(name, basename, sizeof(basename));
3215
3216         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3217         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3218                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3219                         break;
3220
3221         if (!item) {
3222                 rtexture_t *dyntexture;
3223                 // check whether its a dynamic texture
3224                 dyntexture = CL_GetDynTexture( basename );
3225                 if (!add && !dyntexture)
3226                         return NULL;
3227                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3228                 memset(item, 0, sizeof(*item));
3229                 strlcpy(item->basename, basename, sizeof(item->basename));
3230                 item->base = dyntexture; // either NULL or dyntexture handle
3231                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3232                 item->comparewidth = comparewidth;
3233                 item->compareheight = compareheight;
3234                 item->comparecrc = comparecrc;
3235                 item->next = r_skinframe.hash[hashindex];
3236                 r_skinframe.hash[hashindex] = item;
3237         }
3238         else if (textureflags & TEXF_FORCE_RELOAD)
3239         {
3240                 rtexture_t *dyntexture;
3241                 // check whether its a dynamic texture
3242                 dyntexture = CL_GetDynTexture( basename );
3243                 if (!add && !dyntexture)
3244                         return NULL;
3245                 if (item->merged == item->base)
3246                         item->merged = NULL;
3247                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3248                 R_PurgeTexture(item->stain );item->stain  = NULL;
3249                 R_PurgeTexture(item->merged);item->merged = NULL;
3250                 R_PurgeTexture(item->base  );item->base   = NULL;
3251                 R_PurgeTexture(item->pants );item->pants  = NULL;
3252                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3253                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3254                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3255                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3256                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3257         R_PurgeTexture(item->reflect);item->reflect = NULL;
3258                 item->loadsequence = 0;
3259         }
3260         else if( item->base == NULL )
3261         {
3262                 rtexture_t *dyntexture;
3263                 // check whether its a dynamic texture
3264                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3265                 dyntexture = CL_GetDynTexture( basename );
3266                 item->base = dyntexture; // either NULL or dyntexture handle
3267         }
3268
3269         R_SkinFrame_MarkUsed(item);
3270         return item;
3271 }
3272
3273 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3274         { \
3275                 unsigned long long avgcolor[5], wsum; \
3276                 int pix, comp, w; \
3277                 avgcolor[0] = 0; \
3278                 avgcolor[1] = 0; \
3279                 avgcolor[2] = 0; \
3280                 avgcolor[3] = 0; \
3281                 avgcolor[4] = 0; \
3282                 wsum = 0; \
3283                 for(pix = 0; pix < cnt; ++pix) \
3284                 { \
3285                         w = 0; \
3286                         for(comp = 0; comp < 3; ++comp) \
3287                                 w += getpixel; \
3288                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3289                         { \
3290                                 ++wsum; \
3291                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3292                                 w = getpixel; \
3293                                 for(comp = 0; comp < 3; ++comp) \
3294                                         avgcolor[comp] += getpixel * w; \
3295                                 avgcolor[3] += w; \
3296                         } \
3297                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3298                         avgcolor[4] += getpixel; \
3299                 } \
3300                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3301                         avgcolor[3] = 1; \
3302                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3303                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3304                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3305                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3306         }
3307
3308 extern cvar_t gl_picmip;
3309 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3310 {
3311         int j;
3312         unsigned char *pixels;
3313         unsigned char *bumppixels;
3314         unsigned char *basepixels = NULL;
3315         int basepixels_width = 0;
3316         int basepixels_height = 0;
3317         skinframe_t *skinframe;
3318         rtexture_t *ddsbase = NULL;
3319         qboolean ddshasalpha = false;
3320         float ddsavgcolor[4];
3321         char basename[MAX_QPATH];
3322         int miplevel = R_PicmipForFlags(textureflags);
3323         int savemiplevel = miplevel;
3324         int mymiplevel;
3325         char vabuf[1024];
3326
3327         if (cls.state == ca_dedicated)
3328                 return NULL;
3329
3330         // return an existing skinframe if already loaded
3331         // if loading of the first image fails, don't make a new skinframe as it
3332         // would cause all future lookups of this to be missing
3333         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3334         if (skinframe && skinframe->base)
3335                 return skinframe;
3336
3337         Image_StripImageExtension(name, basename, sizeof(basename));
3338
3339         // check for DDS texture file first
3340         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3341         {
3342                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3343                 if (basepixels == NULL)
3344                         return NULL;
3345         }
3346
3347         // FIXME handle miplevel
3348
3349         if (developer_loading.integer)
3350                 Con_Printf("loading skin \"%s\"\n", name);
3351
3352         // we've got some pixels to store, so really allocate this new texture now
3353         if (!skinframe)
3354                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3355         textureflags &= ~TEXF_FORCE_RELOAD;
3356         skinframe->stain = NULL;
3357         skinframe->merged = NULL;
3358         skinframe->base = NULL;
3359         skinframe->pants = NULL;
3360         skinframe->shirt = NULL;
3361         skinframe->nmap = NULL;
3362         skinframe->gloss = NULL;
3363         skinframe->glow = NULL;
3364         skinframe->fog = NULL;
3365         skinframe->reflect = NULL;
3366         skinframe->hasalpha = false;
3367
3368         if (ddsbase)
3369         {
3370                 skinframe->base = ddsbase;
3371                 skinframe->hasalpha = ddshasalpha;
3372                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3373                 if (r_loadfog && skinframe->hasalpha)
3374                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3375                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3376         }
3377         else
3378         {
3379                 basepixels_width = image_width;
3380                 basepixels_height = image_height;
3381                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3382                 if (textureflags & TEXF_ALPHA)
3383                 {
3384                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3385                         {
3386                                 if (basepixels[j] < 255)
3387                                 {
3388                                         skinframe->hasalpha = true;
3389                                         break;
3390                                 }
3391                         }
3392                         if (r_loadfog && skinframe->hasalpha)
3393                         {
3394                                 // has transparent pixels
3395                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3396                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3397                                 {
3398                                         pixels[j+0] = 255;
3399                                         pixels[j+1] = 255;
3400                                         pixels[j+2] = 255;
3401                                         pixels[j+3] = basepixels[j+3];
3402                                 }
3403                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3404                                 Mem_Free(pixels);
3405                         }
3406                 }
3407                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3408 #ifndef USE_GLES2
3409                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3410                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3411                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3412                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3413                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3414 #endif
3415         }
3416
3417         if (r_loaddds)
3418         {
3419                 mymiplevel = savemiplevel;
3420                 if (r_loadnormalmap)
3421                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
3422                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3423                 if (r_loadgloss)
3424                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3425                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3426                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3427                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3428         }
3429
3430         // _norm is the name used by tenebrae and has been adopted as standard
3431         if (r_loadnormalmap && skinframe->nmap == NULL)
3432         {
3433                 mymiplevel = savemiplevel;
3434                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3435                 {
3436                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3437                         Mem_Free(pixels);
3438                         pixels = NULL;
3439                 }
3440                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3441                 {
3442                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3443                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3444                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3445                         Mem_Free(pixels);
3446                         Mem_Free(bumppixels);
3447                 }
3448                 else if (r_shadow_bumpscale_basetexture.value > 0)
3449                 {
3450                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3451                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3452                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3453                         Mem_Free(pixels);
3454                 }
3455 #ifndef USE_GLES2
3456                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3457                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3458 #endif
3459         }
3460
3461         // _luma is supported only for tenebrae compatibility
3462         // _glow is the preferred name
3463         mymiplevel = savemiplevel;
3464         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3465         {
3466                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3467 #ifndef USE_GLES2
3468                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3469                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3470 #endif
3471                 Mem_Free(pixels);pixels = NULL;
3472         }
3473
3474         mymiplevel = savemiplevel;
3475         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3476         {
3477                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3478 #ifndef USE_GLES2
3479                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3480                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3481 #endif
3482                 Mem_Free(pixels);
3483                 pixels = NULL;
3484         }
3485
3486         mymiplevel = savemiplevel;
3487         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3488         {
3489                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3490 #ifndef USE_GLES2
3491                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3492                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3493 #endif
3494                 Mem_Free(pixels);
3495                 pixels = NULL;
3496         }
3497
3498         mymiplevel = savemiplevel;
3499         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3500         {
3501                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3502 #ifndef USE_GLES2
3503                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3504                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3505 #endif
3506                 Mem_Free(pixels);
3507                 pixels = NULL;
3508         }
3509
3510         mymiplevel = savemiplevel;
3511         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3512         {
3513                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3514 #ifndef USE_GLES2
3515                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3516                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3517 #endif
3518                 Mem_Free(pixels);
3519                 pixels = NULL;
3520         }
3521
3522         if (basepixels)
3523                 Mem_Free(basepixels);
3524
3525         return skinframe;
3526 }
3527
3528 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3529 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3530 {
3531         int i;
3532         unsigned char *temp1, *temp2;
3533         skinframe_t *skinframe;
3534         char vabuf[1024];
3535
3536         if (cls.state == ca_dedicated)
3537                 return NULL;
3538
3539         // if already loaded just return it, otherwise make a new skinframe
3540         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3541         if (skinframe->base)
3542                 return skinframe;
3543         textureflags &= ~TEXF_FORCE_RELOAD;
3544
3545         skinframe->stain = NULL;
3546         skinframe->merged = NULL;
3547         skinframe->base = NULL;
3548         skinframe->pants = NULL;
3549         skinframe->shirt = NULL;
3550         skinframe->nmap = NULL;
3551         skinframe->gloss = NULL;
3552         skinframe->glow = NULL;
3553         skinframe->fog = NULL;
3554         skinframe->reflect = NULL;
3555         skinframe->hasalpha = false;
3556
3557         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3558         if (!skindata)
3559                 return NULL;
3560
3561         if (developer_loading.integer)
3562                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3563
3564         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3565         {
3566                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3567                 temp2 = temp1 + width * height * 4;
3568                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3569                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3570                 Mem_Free(temp1);
3571         }
3572         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3573         if (textureflags & TEXF_ALPHA)
3574         {
3575                 for (i = 3;i < width * height * 4;i += 4)
3576                 {
3577                         if (skindata[i] < 255)
3578                         {
3579                                 skinframe->hasalpha = true;
3580                                 break;
3581                         }
3582                 }
3583                 if (r_loadfog && skinframe->hasalpha)
3584                 {
3585                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3586                         memcpy(fogpixels, skindata, width * height * 4);
3587                         for (i = 0;i < width * height * 4;i += 4)
3588                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3589                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3590                         Mem_Free(fogpixels);
3591                 }
3592         }
3593
3594         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3595         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3596
3597         return skinframe;
3598 }
3599
3600 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3601 {
3602         int i;
3603         int featuresmask;
3604         skinframe_t *skinframe;
3605
3606         if (cls.state == ca_dedicated)
3607                 return NULL;
3608
3609         // if already loaded just return it, otherwise make a new skinframe
3610         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3611         if (skinframe->base)
3612                 return skinframe;
3613         //textureflags &= ~TEXF_FORCE_RELOAD;
3614
3615         skinframe->stain = NULL;
3616         skinframe->merged = NULL;
3617         skinframe->base = NULL;
3618         skinframe->pants = NULL;
3619         skinframe->shirt = NULL;
3620         skinframe->nmap = NULL;
3621         skinframe->gloss = NULL;
3622         skinframe->glow = NULL;
3623         skinframe->fog = NULL;
3624         skinframe->reflect = NULL;
3625         skinframe->hasalpha = false;
3626
3627         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3628         if (!skindata)
3629                 return NULL;
3630
3631         if (developer_loading.integer)
3632                 Con_Printf("loading quake skin \"%s\"\n", name);
3633
3634         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3635         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3636         memcpy(skinframe->qpixels, skindata, width*height);
3637         skinframe->qwidth = width;
3638         skinframe->qheight = height;
3639
3640         featuresmask = 0;
3641         for (i = 0;i < width * height;i++)
3642                 featuresmask |= palette_featureflags[skindata[i]];
3643
3644         skinframe->hasalpha = false;
3645         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3646         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3647         skinframe->qgeneratemerged = true;
3648         skinframe->qgeneratebase = skinframe->qhascolormapping;
3649         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3650
3651         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3652         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3653
3654         return skinframe;
3655 }
3656
3657 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3658 {
3659         int width;
3660         int height;
3661         unsigned char *skindata;
3662         char vabuf[1024];
3663
3664         if (!skinframe->qpixels)
3665                 return;
3666
3667         if (!skinframe->qhascolormapping)
3668                 colormapped = false;
3669
3670         if (colormapped)
3671         {
3672                 if (!skinframe->qgeneratebase)
3673                         return;
3674         }
3675         else
3676         {
3677                 if (!skinframe->qgeneratemerged)
3678                         return;
3679         }
3680
3681         width = skinframe->qwidth;
3682         height = skinframe->qheight;
3683         skindata = skinframe->qpixels;
3684
3685         if (skinframe->qgeneratenmap)
3686         {
3687                 unsigned char *temp1, *temp2;
3688                 skinframe->qgeneratenmap = false;
3689                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3690                 temp2 = temp1 + width * height * 4;
3691                 // use either a custom palette or the quake palette
3692                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3693                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3694                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3695                 Mem_Free(temp1);
3696         }
3697
3698         if (skinframe->qgenerateglow)
3699         {
3700                 skinframe->qgenerateglow = false;
3701                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3702         }
3703
3704         if (colormapped)
3705         {
3706                 skinframe->qgeneratebase = false;
3707                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3708                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3709                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3710         }
3711         else
3712         {
3713                 skinframe->qgeneratemerged = false;
3714                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3715         }
3716
3717         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3718         {
3719                 Mem_Free(skinframe->qpixels);
3720                 skinframe->qpixels = NULL;
3721         }
3722 }
3723
3724 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3725 {
3726         int i;
3727         skinframe_t *skinframe;
3728         char vabuf[1024];
3729
3730         if (cls.state == ca_dedicated)
3731                 return NULL;
3732
3733         // if already loaded just return it, otherwise make a new skinframe
3734         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3735         if (skinframe->base)
3736                 return skinframe;
3737         textureflags &= ~TEXF_FORCE_RELOAD;
3738
3739         skinframe->stain = NULL;
3740         skinframe->merged = NULL;
3741         skinframe->base = NULL;
3742         skinframe->pants = NULL;
3743         skinframe->shirt = NULL;
3744         skinframe->nmap = NULL;
3745         skinframe->gloss = NULL;
3746         skinframe->glow = NULL;
3747         skinframe->fog = NULL;
3748         skinframe->reflect = NULL;
3749         skinframe->hasalpha = false;
3750
3751         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3752         if (!skindata)
3753                 return NULL;
3754
3755         if (developer_loading.integer)
3756                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3757
3758         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3759         if (textureflags & TEXF_ALPHA)
3760         {
3761                 for (i = 0;i < width * height;i++)
3762                 {
3763                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3764                         {
3765                                 skinframe->hasalpha = true;
3766                                 break;
3767                         }
3768                 }
3769                 if (r_loadfog && skinframe->hasalpha)
3770                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3771         }
3772
3773         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3774         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3775
3776         return skinframe;
3777 }
3778
3779 skinframe_t *R_SkinFrame_LoadMissing(void)
3780 {
3781         skinframe_t *skinframe;
3782
3783         if (cls.state == ca_dedicated)
3784                 return NULL;
3785
3786         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3787         skinframe->stain = NULL;
3788         skinframe->merged = NULL;
3789         skinframe->base = NULL;
3790         skinframe->pants = NULL;
3791         skinframe->shirt = NULL;
3792         skinframe->nmap = NULL;
3793         skinframe->gloss = NULL;
3794         skinframe->glow = NULL;
3795         skinframe->fog = NULL;
3796         skinframe->reflect = NULL;
3797         skinframe->hasalpha = false;
3798
3799         skinframe->avgcolor[0] = rand() / RAND_MAX;
3800         skinframe->avgcolor[1] = rand() / RAND_MAX;
3801         skinframe->avgcolor[2] = rand() / RAND_MAX;
3802         skinframe->avgcolor[3] = 1;
3803
3804         return skinframe;
3805 }
3806
3807 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3808 typedef struct suffixinfo_s
3809 {
3810         const char *suffix;
3811         qboolean flipx, flipy, flipdiagonal;
3812 }
3813 suffixinfo_t;
3814 static suffixinfo_t suffix[3][6] =
3815 {
3816         {
3817                 {"px",   false, false, false},
3818                 {"nx",   false, false, false},
3819                 {"py",   false, false, false},
3820                 {"ny",   false, false, false},
3821                 {"pz",   false, false, false},
3822                 {"nz",   false, false, false}
3823         },
3824         {
3825                 {"posx", false, false, false},
3826                 {"negx", false, false, false},
3827                 {"posy", false, false, false},
3828                 {"negy", false, false, false},
3829                 {"posz", false, false, false},
3830                 {"negz", false, false, false}
3831         },
3832         {
3833                 {"rt",    true, false,  true},
3834                 {"lf",   false,  true,  true},
3835                 {"ft",    true,  true, false},
3836                 {"bk",   false, false, false},
3837                 {"up",    true, false,  true},
3838                 {"dn",    true, false,  true}
3839         }
3840 };
3841
3842 static int componentorder[4] = {0, 1, 2, 3};
3843
3844 static rtexture_t *R_LoadCubemap(const char *basename)
3845 {
3846         int i, j, cubemapsize;
3847         unsigned char *cubemappixels, *image_buffer;
3848         rtexture_t *cubemaptexture;
3849         char name[256];
3850         // must start 0 so the first loadimagepixels has no requested width/height
3851         cubemapsize = 0;
3852         cubemappixels = NULL;
3853         cubemaptexture = NULL;
3854         // keep trying different suffix groups (posx, px, rt) until one loads
3855         for (j = 0;j < 3 && !cubemappixels;j++)
3856         {
3857                 // load the 6 images in the suffix group
3858                 for (i = 0;i < 6;i++)
3859                 {
3860                         // generate an image name based on the base and and suffix
3861                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3862                         // load it
3863                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3864                         {
3865                                 // an image loaded, make sure width and height are equal
3866                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3867                                 {
3868                                         // if this is the first image to load successfully, allocate the cubemap memory
3869                                         if (!cubemappixels && image_width >= 1)
3870                                         {
3871                                                 cubemapsize = image_width;
3872                                                 // note this clears to black, so unavailable sides are black
3873                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3874                                         }
3875                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3876                                         if (cubemappixels)
3877                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3878                                 }
3879                                 else
3880                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3881                                 // free the image
3882                                 Mem_Free(image_buffer);
3883                         }
3884                 }
3885         }
3886         // if a cubemap loaded, upload it
3887         if (cubemappixels)
3888         {
3889                 if (developer_loading.integer)
3890                         Con_Printf("loading cubemap \"%s\"\n", basename);
3891
3892                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3893                 Mem_Free(cubemappixels);
3894         }
3895         else
3896         {
3897                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3898                 if (developer_loading.integer)
3899                 {
3900                         Con_Printf("(tried tried images ");
3901                         for (j = 0;j < 3;j++)
3902                                 for (i = 0;i < 6;i++)
3903                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3904                         Con_Print(" and was unable to find any of them).\n");
3905                 }
3906         }
3907         return cubemaptexture;
3908 }
3909
3910 rtexture_t *R_GetCubemap(const char *basename)
3911 {
3912         int i;
3913         for (i = 0;i < r_texture_numcubemaps;i++)
3914                 if (r_texture_cubemaps[i] != NULL)
3915                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3916                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3917         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3918                 return r_texture_whitecube;
3919         r_texture_numcubemaps++;
3920         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3921         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3922         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3923         return r_texture_cubemaps[i]->texture;
3924 }
3925
3926 static void R_Main_FreeViewCache(void)
3927 {
3928         if (r_refdef.viewcache.entityvisible)
3929                 Mem_Free(r_refdef.viewcache.entityvisible);
3930         if (r_refdef.viewcache.world_pvsbits)
3931                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3932         if (r_refdef.viewcache.world_leafvisible)
3933                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3934         if (r_refdef.viewcache.world_surfacevisible)
3935                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3936         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3937 }
3938
3939 static void R_Main_ResizeViewCache(void)
3940 {
3941         int numentities = r_refdef.scene.numentities;
3942         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3943         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3944         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3945         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3946         if (r_refdef.viewcache.maxentities < numentities)
3947         {
3948                 r_refdef.viewcache.maxentities = numentities;
3949                 if (r_refdef.viewcache.entityvisible)
3950                         Mem_Free(r_refdef.viewcache.entityvisible);
3951                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3952         }
3953         if (r_refdef.viewcache.world_numclusters != numclusters)
3954         {
3955                 r_refdef.viewcache.world_numclusters = numclusters;
3956                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3957                 if (r_refdef.viewcache.world_pvsbits)
3958                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3959                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3960         }
3961         if (r_refdef.viewcache.world_numleafs != numleafs)
3962         {
3963                 r_refdef.viewcache.world_numleafs = numleafs;
3964                 if (r_refdef.viewcache.world_leafvisible)
3965                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3966                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3967         }
3968         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3969         {
3970                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3971                 if (r_refdef.viewcache.world_surfacevisible)
3972                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3973                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3974         }
3975 }
3976
3977 extern rtexture_t *loadingscreentexture;
3978 static void gl_main_start(void)
3979 {
3980         loadingscreentexture = NULL;
3981         r_texture_blanknormalmap = NULL;
3982         r_texture_white = NULL;
3983         r_texture_grey128 = NULL;
3984         r_texture_black = NULL;
3985         r_texture_whitecube = NULL;
3986         r_texture_normalizationcube = NULL;
3987         r_texture_fogattenuation = NULL;
3988         r_texture_fogheighttexture = NULL;
3989         r_texture_gammaramps = NULL;
3990         r_texture_numcubemaps = 0;
3991         r_uniformbufferalignment = 32;
3992
3993         r_loaddds = r_texture_dds_load.integer != 0;
3994         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3995
3996         switch(vid.renderpath)
3997         {
3998         case RENDERPATH_GL20:
3999         case RENDERPATH_D3D9:
4000         case RENDERPATH_D3D10:
4001         case RENDERPATH_D3D11:
4002         case RENDERPATH_SOFT:
4003         case RENDERPATH_GLES2:
4004                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4005                 Cvar_SetValueQuick(&gl_combine, 1);
4006                 Cvar_SetValueQuick(&r_glsl, 1);
4007                 r_loadnormalmap = true;
4008                 r_loadgloss = true;
4009                 r_loadfog = false;
4010                 if (vid.support.arb_uniform_buffer_object)
4011                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4012                 break;
4013         case RENDERPATH_GL13:
4014         case RENDERPATH_GLES1:
4015                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4016                 Cvar_SetValueQuick(&gl_combine, 1);
4017                 Cvar_SetValueQuick(&r_glsl, 0);
4018                 r_loadnormalmap = false;
4019                 r_loadgloss = false;
4020                 r_loadfog = true;
4021                 break;
4022         case RENDERPATH_GL11:
4023                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4024                 Cvar_SetValueQuick(&gl_combine, 0);
4025                 Cvar_SetValueQuick(&r_glsl, 0);
4026                 r_loadnormalmap = false;
4027                 r_loadgloss = false;
4028                 r_loadfog = true;
4029                 break;
4030         }
4031
4032         R_AnimCache_Free();
4033         R_FrameData_Reset();
4034         R_BufferData_Reset();
4035
4036         r_numqueries = 0;
4037         r_maxqueries = 0;
4038         memset(r_queries, 0, sizeof(r_queries));
4039
4040         r_qwskincache = NULL;
4041         r_qwskincache_size = 0;
4042
4043         // due to caching of texture_t references, the collision cache must be reset
4044         Collision_Cache_Reset(true);
4045
4046         // set up r_skinframe loading system for textures
4047         memset(&r_skinframe, 0, sizeof(r_skinframe));
4048         r_skinframe.loadsequence = 1;
4049         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4050
4051         r_main_texturepool = R_AllocTexturePool();
4052         R_BuildBlankTextures();
4053         R_BuildNoTexture();
4054         if (vid.support.arb_texture_cube_map)
4055         {
4056                 R_BuildWhiteCube();
4057                 R_BuildNormalizationCube();
4058         }
4059         r_texture_fogattenuation = NULL;
4060         r_texture_fogheighttexture = NULL;
4061         r_texture_gammaramps = NULL;
4062         //r_texture_fogintensity = NULL;
4063         memset(&r_fb, 0, sizeof(r_fb));
4064         r_glsl_permutation = NULL;
4065         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4066         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4067         glslshaderstring = NULL;
4068 #ifdef SUPPORTD3D
4069         r_hlsl_permutation = NULL;
4070         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4071         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4072 #endif
4073         hlslshaderstring = NULL;
4074         memset(&r_svbsp, 0, sizeof (r_svbsp));
4075
4076         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4077         r_texture_numcubemaps = 0;
4078
4079         r_refdef.fogmasktable_density = 0;
4080 }
4081
4082 static void gl_main_shutdown(void)
4083 {
4084         R_AnimCache_Free();
4085         R_FrameData_Reset();
4086         R_BufferData_Reset();
4087
4088         R_Main_FreeViewCache();
4089
4090         switch(vid.renderpath)
4091         {
4092         case RENDERPATH_GL11:
4093         case RENDERPATH_GL13:
4094         case RENDERPATH_GL20:
4095         case RENDERPATH_GLES1:
4096         case RENDERPATH_GLES2:
4097 #ifdef GL_SAMPLES_PASSED_ARB
4098                 if (r_maxqueries)
4099                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4100 #endif
4101                 break;
4102         case RENDERPATH_D3D9:
4103                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4104                 break;
4105         case RENDERPATH_D3D10:
4106                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4107                 break;
4108         case RENDERPATH_D3D11:
4109                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4110                 break;
4111         case RENDERPATH_SOFT:
4112                 break;
4113         }
4114
4115         r_numqueries = 0;
4116         r_maxqueries = 0;
4117         memset(r_queries, 0, sizeof(r_queries));
4118
4119         r_qwskincache = NULL;
4120         r_qwskincache_size = 0;
4121
4122         // clear out the r_skinframe state
4123         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4124         memset(&r_skinframe, 0, sizeof(r_skinframe));
4125
4126         if (r_svbsp.nodes)
4127                 Mem_Free(r_svbsp.nodes);
4128         memset(&r_svbsp, 0, sizeof (r_svbsp));
4129         R_FreeTexturePool(&r_main_texturepool);
4130         loadingscreentexture = NULL;
4131         r_texture_blanknormalmap = NULL;
4132         r_texture_white = NULL;
4133         r_texture_grey128 = NULL;
4134         r_texture_black = NULL;
4135         r_texture_whitecube = NULL;
4136         r_texture_normalizationcube = NULL;
4137         r_texture_fogattenuation = NULL;
4138         r_texture_fogheighttexture = NULL;
4139         r_texture_gammaramps = NULL;
4140         r_texture_numcubemaps = 0;
4141         //r_texture_fogintensity = NULL;
4142         memset(&r_fb, 0, sizeof(r_fb));
4143         R_GLSL_Restart_f();
4144
4145         r_glsl_permutation = NULL;
4146         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4147         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4148         glslshaderstring = NULL;
4149 #ifdef SUPPORTD3D
4150         r_hlsl_permutation = NULL;
4151         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4152         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4153 #endif
4154         hlslshaderstring = NULL;
4155 }
4156
4157 static void gl_main_newmap(void)
4158 {
4159         // FIXME: move this code to client
4160         char *entities, entname[MAX_QPATH];
4161         if (r_qwskincache)
4162                 Mem_Free(r_qwskincache);
4163         r_qwskincache = NULL;
4164         r_qwskincache_size = 0;
4165         if (cl.worldmodel)
4166         {
4167                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4168                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4169                 {
4170                         CL_ParseEntityLump(entities);
4171                         Mem_Free(entities);
4172                         return;
4173                 }
4174                 if (cl.worldmodel->brush.entities)
4175                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4176         }
4177         R_Main_FreeViewCache();
4178
4179         R_FrameData_Reset();
4180         R_BufferData_Reset();
4181 }
4182
4183 void GL_Main_Init(void)
4184 {
4185         int i;
4186         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4187
4188         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4189         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4190         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4191         if (gamemode == GAME_NEHAHRA)
4192         {
4193                 Cvar_RegisterVariable (&gl_fogenable);
4194                 Cvar_RegisterVariable (&gl_fogdensity);
4195                 Cvar_RegisterVariable (&gl_fogred);
4196                 Cvar_RegisterVariable (&gl_foggreen);
4197                 Cvar_RegisterVariable (&gl_fogblue);
4198                 Cvar_RegisterVariable (&gl_fogstart);
4199                 Cvar_RegisterVariable (&gl_fogend);
4200                 Cvar_RegisterVariable (&gl_skyclip);
4201         }
4202         Cvar_RegisterVariable(&r_motionblur);
4203         Cvar_RegisterVariable(&r_damageblur);
4204         Cvar_RegisterVariable(&r_motionblur_averaging);
4205         Cvar_RegisterVariable(&r_motionblur_randomize);
4206         Cvar_RegisterVariable(&r_motionblur_minblur);
4207         Cvar_RegisterVariable(&r_motionblur_maxblur);
4208         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4209         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4210         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4211         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4212         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4213         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4214         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4215         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4216         Cvar_RegisterVariable(&r_equalize_entities_by);
4217         Cvar_RegisterVariable(&r_equalize_entities_to);
4218         Cvar_RegisterVariable(&r_depthfirst);
4219         Cvar_RegisterVariable(&r_useinfinitefarclip);
4220         Cvar_RegisterVariable(&r_farclip_base);
4221         Cvar_RegisterVariable(&r_farclip_world);
4222         Cvar_RegisterVariable(&r_nearclip);
4223         Cvar_RegisterVariable(&r_deformvertexes);
4224         Cvar_RegisterVariable(&r_transparent);
4225         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4226         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4227         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4228         Cvar_RegisterVariable(&r_showoverdraw);
4229         Cvar_RegisterVariable(&r_showbboxes);
4230         Cvar_RegisterVariable(&r_showsurfaces);
4231         Cvar_RegisterVariable(&r_showtris);
4232         Cvar_RegisterVariable(&r_shownormals);
4233         Cvar_RegisterVariable(&r_showlighting);
4234         Cvar_RegisterVariable(&r_showshadowvolumes);
4235         Cvar_RegisterVariable(&r_showcollisionbrushes);
4236         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4237         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4238         Cvar_RegisterVariable(&r_showdisabledepthtest);
4239         Cvar_RegisterVariable(&r_drawportals);
4240         Cvar_RegisterVariable(&r_drawentities);
4241         Cvar_RegisterVariable(&r_draw2d);
4242         Cvar_RegisterVariable(&r_drawworld);
4243         Cvar_RegisterVariable(&r_cullentities_trace);
4244         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4245         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4246         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4247         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4248         Cvar_RegisterVariable(&r_sortentities);
4249         Cvar_RegisterVariable(&r_drawviewmodel);
4250         Cvar_RegisterVariable(&r_drawexteriormodel);
4251         Cvar_RegisterVariable(&r_speeds);
4252         Cvar_RegisterVariable(&r_fullbrights);
4253         Cvar_RegisterVariable(&r_wateralpha);
4254         Cvar_RegisterVariable(&r_dynamic);
4255         Cvar_RegisterVariable(&r_fakelight);
4256         Cvar_RegisterVariable(&r_fakelight_intensity);
4257         Cvar_RegisterVariable(&r_fullbright);
4258         Cvar_RegisterVariable(&r_shadows);
4259         Cvar_RegisterVariable(&r_shadows_darken);
4260         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4261         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4262         Cvar_RegisterVariable(&r_shadows_throwdistance);
4263         Cvar_RegisterVariable(&r_shadows_throwdirection);
4264         Cvar_RegisterVariable(&r_shadows_focus);
4265         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4266         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4267         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4268         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4269         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4270         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4271         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4272         Cvar_RegisterVariable(&r_fog_exp2);
4273         Cvar_RegisterVariable(&r_fog_clear);
4274         Cvar_RegisterVariable(&r_drawfog);
4275         Cvar_RegisterVariable(&r_transparentdepthmasking);
4276         Cvar_RegisterVariable(&r_transparent_sortmindist);
4277         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4278         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4279         Cvar_RegisterVariable(&r_texture_dds_load);
4280         Cvar_RegisterVariable(&r_texture_dds_save);
4281         Cvar_RegisterVariable(&r_textureunits);
4282         Cvar_RegisterVariable(&gl_combine);
4283         Cvar_RegisterVariable(&r_usedepthtextures);
4284         Cvar_RegisterVariable(&r_viewfbo);
4285         Cvar_RegisterVariable(&r_viewscale);
4286         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4287         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4288         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4289         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4290         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4291         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4292         Cvar_RegisterVariable(&r_glsl);
4293         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4294         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4295         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4296         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4297         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4298         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4299         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4300         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4301         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4302         Cvar_RegisterVariable(&r_glsl_postprocess);
4303         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4304         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4305         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4306         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4307         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4308         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4309         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4310         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4311         Cvar_RegisterVariable(&r_celshading);
4312         Cvar_RegisterVariable(&r_celoutlines);
4313
4314         Cvar_RegisterVariable(&r_water);
4315         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4316         Cvar_RegisterVariable(&r_water_clippingplanebias);
4317         Cvar_RegisterVariable(&r_water_refractdistort);
4318         Cvar_RegisterVariable(&r_water_reflectdistort);
4319         Cvar_RegisterVariable(&r_water_scissormode);
4320         Cvar_RegisterVariable(&r_water_lowquality);
4321         Cvar_RegisterVariable(&r_water_hideplayer);
4322         Cvar_RegisterVariable(&r_water_fbo);
4323
4324         Cvar_RegisterVariable(&r_lerpsprites);
4325         Cvar_RegisterVariable(&r_lerpmodels);
4326         Cvar_RegisterVariable(&r_lerplightstyles);
4327         Cvar_RegisterVariable(&r_waterscroll);
4328         Cvar_RegisterVariable(&r_bloom);
4329         Cvar_RegisterVariable(&r_bloom_colorscale);
4330         Cvar_RegisterVariable(&r_bloom_brighten);
4331         Cvar_RegisterVariable(&r_bloom_blur);
4332         Cvar_RegisterVariable(&r_bloom_resolution);
4333         Cvar_RegisterVariable(&r_bloom_colorexponent);
4334         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4335         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4336         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4337         Cvar_RegisterVariable(&r_hdr_glowintensity);
4338         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4339         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4340         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4341         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4342         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4343         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4344         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4345         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4346         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4347         Cvar_RegisterVariable(&developer_texturelogging);
4348         Cvar_RegisterVariable(&gl_lightmaps);
4349         Cvar_RegisterVariable(&r_test);
4350         Cvar_RegisterVariable(&r_batch_multidraw);
4351         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4352         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4353         Cvar_RegisterVariable(&r_glsl_skeletal);
4354         Cvar_RegisterVariable(&r_glsl_saturation);
4355         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4356         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4357         Cvar_RegisterVariable(&r_framedatasize);
4358         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4359                 Cvar_RegisterVariable(&r_buffermegs[i]);
4360         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4361         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4362                 Cvar_SetValue("r_fullbrights", 0);
4363         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4364 }
4365
4366 void Render_Init(void)
4367 {
4368         gl_backend_init();
4369         R_Textures_Init();
4370         GL_Main_Init();
4371         Font_Init();
4372         GL_Draw_Init();
4373         R_Shadow_Init();
4374         R_Sky_Init();
4375         GL_Surf_Init();
4376         Sbar_Init();
4377         R_Particles_Init();
4378         R_Explosion_Init();
4379         R_LightningBeams_Init();
4380         Mod_RenderInit();
4381 }
4382
4383 /*
4384 ===============
4385 GL_Init
4386 ===============
4387 */
4388 #ifndef USE_GLES2
4389 extern char *ENGINE_EXTENSIONS;
4390 void GL_Init (void)
4391 {
4392         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4393         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4394         gl_version = (const char *)qglGetString(GL_VERSION);
4395         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4396
4397         if (!gl_extensions)
4398                 gl_extensions = "";
4399         if (!gl_platformextensions)
4400                 gl_platformextensions = "";
4401
4402         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4403         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4404         Con_Printf("GL_VERSION: %s\n", gl_version);
4405         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4406         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4407
4408         VID_CheckExtensions();
4409
4410         // LordHavoc: report supported extensions
4411         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4412
4413         // clear to black (loading plaque will be seen over this)
4414         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4415 }
4416 #endif
4417
4418 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4419 {
4420         int i;
4421         mplane_t *p;
4422         if (r_trippy.integer)
4423                 return false;
4424         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4425         {
4426                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4427                 if (i == 4)
4428                         continue;
4429                 p = r_refdef.view.frustum + i;
4430                 switch(p->signbits)
4431                 {
4432                 default:
4433                 case 0:
4434                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4435                                 return true;
4436                         break;
4437                 case 1:
4438                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4439                                 return true;
4440                         break;
4441                 case 2:
4442                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 case 3:
4446                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4447                                 return true;
4448                         break;
4449                 case 4:
4450                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4451                                 return true;
4452                         break;
4453                 case 5:
4454                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4455                                 return true;
4456                         break;
4457                 case 6:
4458                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4459                                 return true;
4460                         break;
4461                 case 7:
4462                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4463                                 return true;
4464                         break;
4465                 }
4466         }
4467         return false;
4468 }
4469
4470 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4471 {
4472         int i;
4473         const mplane_t *p;
4474         if (r_trippy.integer)
4475                 return false;
4476         for (i = 0;i < numplanes;i++)
4477         {
4478                 p = planes + i;
4479                 switch(p->signbits)
4480                 {
4481                 default:
4482                 case 0:
4483                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4484                                 return true;
4485                         break;
4486                 case 1:
4487                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4488                                 return true;
4489                         break;
4490                 case 2:
4491                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4492                                 return true;
4493                         break;
4494                 case 3:
4495                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4496                                 return true;
4497                         break;
4498                 case 4:
4499                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4500                                 return true;
4501                         break;
4502                 case 5:
4503                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4504                                 return true;
4505                         break;
4506                 case 6:
4507                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4508                                 return true;
4509                         break;
4510                 case 7:
4511                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4512                                 return true;
4513                         break;
4514                 }
4515         }
4516         return false;
4517 }
4518
4519 //==================================================================================
4520
4521 // LordHavoc: this stores temporary data used within the same frame
4522
4523 typedef struct r_framedata_mem_s
4524 {
4525         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4526         size_t size; // how much usable space
4527         size_t current; // how much space in use
4528         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4529         size_t wantedsize; // how much space was allocated
4530         unsigned char *data; // start of real data (16byte aligned)
4531 }
4532 r_framedata_mem_t;
4533
4534 static r_framedata_mem_t *r_framedata_mem;
4535
4536 void R_FrameData_Reset(void)
4537 {
4538         while (r_framedata_mem)
4539         {
4540                 r_framedata_mem_t *next = r_framedata_mem->purge;
4541                 Mem_Free(r_framedata_mem);
4542                 r_framedata_mem = next;
4543         }
4544 }
4545
4546 static void R_FrameData_Resize(qboolean mustgrow)
4547 {
4548         size_t wantedsize;
4549         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4550         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4551         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4552         {
4553                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4554                 newmem->wantedsize = wantedsize;
4555                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4556                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4557                 newmem->current = 0;
4558                 newmem->mark = 0;
4559                 newmem->purge = r_framedata_mem;
4560                 r_framedata_mem = newmem;
4561         }
4562 }
4563
4564 void R_FrameData_NewFrame(void)
4565 {
4566         R_FrameData_Resize(false);
4567         if (!r_framedata_mem)
4568                 return;
4569         // if we ran out of space on the last frame, free the old memory now
4570         while (r_framedata_mem->purge)
4571         {
4572                 // repeatedly remove the second item in the list, leaving only head
4573                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4574                 Mem_Free(r_framedata_mem->purge);
4575                 r_framedata_mem->purge = next;
4576         }
4577         // reset the current mem pointer
4578         r_framedata_mem->current = 0;
4579         r_framedata_mem->mark = 0;
4580 }
4581
4582 void *R_FrameData_Alloc(size_t size)
4583 {
4584         void *data;
4585         float newvalue;
4586
4587         // align to 16 byte boundary - the data pointer is already aligned, so we
4588         // only need to ensure the size of every allocation is also aligned
4589         size = (size + 15) & ~15;
4590
4591         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4592         {
4593                 // emergency - we ran out of space, allocate more memory
4594                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4595                 // this might not be a growing it, but we'll allocate another buffer every time
4596                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4597                 R_FrameData_Resize(true);
4598         }
4599
4600         data = r_framedata_mem->data + r_framedata_mem->current;
4601         r_framedata_mem->current += size;
4602
4603         // count the usage for stats
4604         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4605         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4606
4607         return (void *)data;
4608 }
4609
4610 void *R_FrameData_Store(size_t size, void *data)
4611 {
4612         void *d = R_FrameData_Alloc(size);
4613         if (d && data)
4614                 memcpy(d, data, size);
4615         return d;
4616 }
4617
4618 void R_FrameData_SetMark(void)
4619 {
4620         if (!r_framedata_mem)
4621                 return;
4622         r_framedata_mem->mark = r_framedata_mem->current;
4623 }
4624
4625 void R_FrameData_ReturnToMark(void)
4626 {
4627         if (!r_framedata_mem)
4628                 return;
4629         r_framedata_mem->current = r_framedata_mem->mark;
4630 }
4631
4632 //==================================================================================
4633
4634 // avoid reusing the same buffer objects on consecutive frames
4635 #define R_BUFFERDATA_CYCLE 3
4636
4637 typedef struct r_bufferdata_buffer_s
4638 {
4639         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4640         size_t size; // how much usable space
4641         size_t current; // how much space in use
4642         r_meshbuffer_t *buffer; // the buffer itself
4643 }
4644 r_bufferdata_buffer_t;
4645
4646 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4647 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4648
4649 /// frees all dynamic buffers
4650 void R_BufferData_Reset(void)
4651 {
4652         int cycle, type;
4653         r_bufferdata_buffer_t **p, *mem;
4654         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4655         {
4656                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4657                 {
4658                         // free all buffers
4659                         p = &r_bufferdata_buffer[cycle][type];
4660                         while (*p)
4661                         {
4662                                 mem = *p;
4663                                 *p = (*p)->purge;
4664                                 if (mem->buffer)
4665                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4666                                 Mem_Free(mem);
4667                         }
4668                 }
4669         }
4670 }
4671
4672 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4673 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4674 {
4675         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4676         size_t size;
4677         float newvalue = r_buffermegs[type].value;
4678
4679         // increase the cvar if we have to (but only if we already have a mem)
4680         if (mustgrow && mem)
4681                 newvalue *= 2.0f;
4682         newvalue = bound(0.25f, newvalue, 256.0f);
4683         while (newvalue * 1024*1024 < minsize)
4684                 newvalue *= 2.0f;
4685
4686         // clamp the cvar to valid range
4687         newvalue = bound(0.25f, newvalue, 256.0f);
4688         if (r_buffermegs[type].value != newvalue)
4689                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4690
4691         // calculate size in bytes
4692         size = (size_t)(newvalue * 1024*1024);
4693         size = bound(131072, size, 256*1024*1024);
4694
4695         // allocate a new buffer if the size is different (purge old one later)
4696         // or if we were told we must grow the buffer
4697         if (!mem || mem->size != size || mustgrow)
4698         {
4699                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4700                 mem->size = size;
4701                 mem->current = 0;
4702                 if (type == R_BUFFERDATA_VERTEX)
4703                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4704                 else if (type == R_BUFFERDATA_INDEX16)
4705                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4706                 else if (type == R_BUFFERDATA_INDEX32)
4707                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4708                 else if (type == R_BUFFERDATA_UNIFORM)
4709                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4710                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4711                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4712         }
4713 }
4714
4715 void R_BufferData_NewFrame(void)
4716 {
4717         int type;
4718         r_bufferdata_buffer_t **p, *mem;
4719         // cycle to the next frame's buffers
4720         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4721         // if we ran out of space on the last time we used these buffers, free the old memory now
4722         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4723         {
4724                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4725                 {
4726                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4727                         // free all but the head buffer, this is how we recycle obsolete
4728                         // buffers after they are no longer in use
4729                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4730                         while (*p)
4731                         {
4732                                 mem = *p;
4733                                 *p = (*p)->purge;
4734                                 if (mem->buffer)
4735                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4736                                 Mem_Free(mem);
4737                         }
4738                         // reset the current offset
4739                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4740                 }
4741         }
4742 }
4743
4744 r_meshbuffer_t *R_BufferData_Store(size_t datasize, void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4745 {
4746         r_bufferdata_buffer_t *mem;
4747         int offset = 0;
4748         int padsize;
4749
4750         *returnbufferoffset = 0;
4751
4752         // align size to a byte boundary appropriate for the buffer type, this
4753         // makes all allocations have aligned start offsets
4754         if (type == R_BUFFERDATA_UNIFORM)
4755                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4756         else
4757                 padsize = (datasize + 15) & ~15;
4758
4759         // if we ran out of space in this buffer we must allocate a new one
4760         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)
4761                 R_BufferData_Resize(type, true, padsize);
4762
4763         // if the resize did not give us enough memory, fail
4764         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)
4765                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4766
4767         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4768         offset = mem->current;
4769         mem->current += padsize;
4770
4771         // upload the data to the buffer at the chosen offset
4772         if (offset == 0)
4773                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4774         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4775
4776         // count the usage for stats
4777         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4778         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4779
4780         // return the buffer offset
4781         *returnbufferoffset = offset;
4782
4783         return mem->buffer;
4784 }
4785
4786 //==================================================================================
4787
4788 // LordHavoc: animcache originally written by Echon, rewritten since then
4789
4790 /**
4791  * Animation cache prevents re-generating mesh data for an animated model
4792  * multiple times in one frame for lighting, shadowing, reflections, etc.
4793  */
4794
4795 void R_AnimCache_Free(void)
4796 {
4797 }
4798
4799 void R_AnimCache_ClearCache(void)
4800 {
4801         int i;
4802         entity_render_t *ent;
4803
4804         for (i = 0;i < r_refdef.scene.numentities;i++)
4805         {
4806                 ent = r_refdef.scene.entities[i];
4807                 ent->animcache_vertex3f = NULL;
4808                 ent->animcache_vertex3f_vertexbuffer = NULL;
4809                 ent->animcache_vertex3f_bufferoffset = 0;
4810                 ent->animcache_normal3f = NULL;
4811                 ent->animcache_normal3f_vertexbuffer = NULL;
4812                 ent->animcache_normal3f_bufferoffset = 0;
4813                 ent->animcache_svector3f = NULL;
4814                 ent->animcache_svector3f_vertexbuffer = NULL;
4815                 ent->animcache_svector3f_bufferoffset = 0;
4816                 ent->animcache_tvector3f = NULL;
4817                 ent->animcache_tvector3f_vertexbuffer = NULL;
4818                 ent->animcache_tvector3f_bufferoffset = 0;
4819                 ent->animcache_vertexmesh = NULL;
4820                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4821                 ent->animcache_vertexmesh_bufferoffset = 0;
4822                 ent->animcache_skeletaltransform3x4 = NULL;
4823                 ent->animcache_skeletaltransform3x4buffer = NULL;
4824                 ent->animcache_skeletaltransform3x4offset = 0;
4825                 ent->animcache_skeletaltransform3x4size = 0;
4826         }
4827 }
4828
4829 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4830 {
4831         int i;
4832
4833         // check if we need the meshbuffers
4834         if (!vid.useinterleavedarrays)
4835                 return;
4836
4837         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4838                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4839         // TODO: upload vertexbuffer?
4840         if (ent->animcache_vertexmesh)
4841         {
4842                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4843                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4844                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4845                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4846                 for (i = 0;i < numvertices;i++)
4847                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4848                 if (ent->animcache_svector3f)
4849                         for (i = 0;i < numvertices;i++)
4850                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4851                 if (ent->animcache_tvector3f)
4852                         for (i = 0;i < numvertices;i++)
4853                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4854                 if (ent->animcache_normal3f)
4855                         for (i = 0;i < numvertices;i++)
4856                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4857         }
4858 }
4859
4860 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4861 {
4862         dp_model_t *model = ent->model;
4863         int numvertices;
4864
4865         // see if this ent is worth caching
4866         if (!model || !model->Draw || !model->AnimateVertices)
4867                 return false;
4868         // nothing to cache if it contains no animations and has no skeleton
4869         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4870                 return false;
4871         // see if it is already cached for gpuskeletal
4872         if (ent->animcache_skeletaltransform3x4)
4873                 return false;
4874         // see if it is already cached as a mesh
4875         if (ent->animcache_vertex3f)
4876         {
4877                 // check if we need to add normals or tangents
4878                 if (ent->animcache_normal3f)
4879                         wantnormals = false;
4880                 if (ent->animcache_svector3f)
4881                         wanttangents = false;
4882                 if (!wantnormals && !wanttangents)
4883                         return false;
4884         }
4885
4886         // check which kind of cache we need to generate
4887         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4888         {
4889                 // cache the skeleton so the vertex shader can use it
4890                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4891                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4892                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4893                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4894                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4895                 // note: this can fail if the buffer is at the grow limit
4896                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4897                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4898         }
4899         else if (ent->animcache_vertex3f)
4900         {
4901                 // mesh was already cached but we may need to add normals/tangents
4902                 // (this only happens with multiple views, reflections, cameras, etc)
4903                 if (wantnormals || wanttangents)
4904                 {
4905                         numvertices = model->surfmesh.num_vertices;
4906                         if (wantnormals)
4907                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4908                         if (wanttangents)
4909                         {
4910                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4911                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4912                         }
4913                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4914                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4915                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4916                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4917                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4918                 }
4919         }
4920         else
4921         {
4922                 // generate mesh cache
4923                 numvertices = model->surfmesh.num_vertices;
4924                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4925                 if (wantnormals)
4926                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4927                 if (wanttangents)
4928                 {
4929                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4930                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4931                 }
4932                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4933                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4934                 if (wantnormals || wanttangents)
4935                 {
4936                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4937                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4938                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4939                 }
4940                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4941                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4942                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4943         }
4944         return true;
4945 }
4946
4947 void R_AnimCache_CacheVisibleEntities(void)
4948 {
4949         int i;
4950         qboolean wantnormals = true;
4951         qboolean wanttangents = !r_showsurfaces.integer;
4952
4953         switch(vid.renderpath)
4954         {
4955         case RENDERPATH_GL20:
4956         case RENDERPATH_D3D9:
4957         case RENDERPATH_D3D10:
4958         case RENDERPATH_D3D11:
4959         case RENDERPATH_GLES2:
4960                 break;
4961         case RENDERPATH_GL11:
4962         case RENDERPATH_GL13:
4963         case RENDERPATH_GLES1:
4964                 wanttangents = false;
4965                 break;
4966         case RENDERPATH_SOFT:
4967                 break;
4968         }
4969
4970         if (r_shownormals.integer)
4971                 wanttangents = wantnormals = true;
4972
4973         // TODO: thread this
4974         // NOTE: R_PrepareRTLights() also caches entities
4975
4976         for (i = 0;i < r_refdef.scene.numentities;i++)
4977                 if (r_refdef.viewcache.entityvisible[i])
4978                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4979 }
4980
4981 //==================================================================================
4982
4983 extern cvar_t r_overheadsprites_pushback;
4984
4985 static void R_View_UpdateEntityLighting (void)
4986 {
4987         int i;
4988         entity_render_t *ent;
4989         vec3_t tempdiffusenormal, avg;
4990         vec_t f, fa, fd, fdd;
4991         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4992
4993         for (i = 0;i < r_refdef.scene.numentities;i++)
4994         {
4995                 ent = r_refdef.scene.entities[i];
4996
4997                 // skip unseen models
4998                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4999                         continue;
5000
5001                 // skip bsp models
5002                 if (ent->model && ent->model == cl.worldmodel)
5003                 {
5004                         // TODO: use modellight for r_ambient settings on world?
5005                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5006                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5007                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5008                         continue;
5009                 }
5010                 
5011                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5012                 {
5013                         // aleady updated by CSQC
5014                         // TODO: force modellight on BSP models in this case?
5015                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5016                 }
5017                 else
5018                 {
5019                         // fetch the lighting from the worldmodel data
5020                         VectorClear(ent->modellight_ambient);
5021                         VectorClear(ent->modellight_diffuse);
5022                         VectorClear(tempdiffusenormal);
5023                         if (ent->flags & RENDER_LIGHT)
5024                         {
5025                                 vec3_t org;
5026                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5027
5028                                 // complete lightning for lit sprites
5029                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5030                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5031                                 {
5032                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5033                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5034                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5035                                 }
5036                                 else
5037                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5038
5039                                 if(ent->flags & RENDER_EQUALIZE)
5040                                 {
5041                                         // first fix up ambient lighting...
5042                                         if(r_equalize_entities_minambient.value > 0)
5043                                         {
5044                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5045                                                 if(fd > 0)
5046                                                 {
5047                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5048                                                         if(fa < r_equalize_entities_minambient.value * fd)
5049                                                         {
5050                                                                 // solve:
5051                                                                 //   fa'/fd' = minambient
5052                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5053                                                                 //   ...
5054                                                                 //   fa' = fd' * minambient
5055                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5056                                                                 //   ...
5057                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5058                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5059                                                                 //   ...
5060                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5061                                                                 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
5062                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5063                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5064                                                         }
5065                                                 }
5066                                         }
5067
5068                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5069                                         {
5070                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5071                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5072                                                 f = fa + 0.25 * fd;
5073                                                 if(f > 0)
5074                                                 {
5075                                                         // adjust brightness and saturation to target
5076                                                         avg[0] = avg[1] = avg[2] = fa / f;
5077                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5078                                                         avg[0] = avg[1] = avg[2] = fd / f;
5079                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5080                                                 }
5081                                         }
5082                                 }
5083                         }
5084                         else // highly rare
5085                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5086                 }
5087
5088                 // move the light direction into modelspace coordinates for lighting code
5089                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5090                 if(VectorLength2(ent->modellight_lightdir) == 0)
5091                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5092                 VectorNormalize(ent->modellight_lightdir);
5093         }
5094 }
5095
5096 #define MAX_LINEOFSIGHTTRACES 64
5097
5098 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5099 {
5100         int i;
5101         vec3_t boxmins, boxmaxs;
5102         vec3_t start;
5103         vec3_t end;
5104         dp_model_t *model = r_refdef.scene.worldmodel;
5105
5106         if (!model || !model->brush.TraceLineOfSight)
5107                 return true;
5108
5109         // expand the box a little
5110         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5111         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5112         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5113         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5114         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5115         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5116
5117         // return true if eye is inside enlarged box
5118         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5119                 return true;
5120
5121         // try center
5122         VectorCopy(eye, start);
5123         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5124         if (model->brush.TraceLineOfSight(model, start, end))
5125                 return true;
5126
5127         // try various random positions
5128         for (i = 0;i < numsamples;i++)
5129         {
5130                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5131                 if (model->brush.TraceLineOfSight(model, start, end))
5132                         return true;
5133         }
5134
5135         return false;
5136 }
5137
5138
5139 static void R_View_UpdateEntityVisible (void)
5140 {
5141         int i;
5142         int renderimask;
5143         int samples;
5144         entity_render_t *ent;
5145
5146         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5147                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5148                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5149                 :                                                          RENDER_EXTERIORMODEL;
5150         if (!r_drawviewmodel.integer)
5151                 renderimask |= RENDER_VIEWMODEL;
5152         if (!r_drawexteriormodel.integer)
5153                 renderimask |= RENDER_EXTERIORMODEL;
5154         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5155         {
5156                 // worldmodel can check visibility
5157                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5158                 for (i = 0;i < r_refdef.scene.numentities;i++)
5159                 {
5160                         ent = r_refdef.scene.entities[i];
5161                         if (!(ent->flags & renderimask))
5162                         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)))
5163                         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))
5164                                 r_refdef.viewcache.entityvisible[i] = true;
5165                 }
5166         }
5167         else
5168         {
5169                 // no worldmodel or it can't check visibility
5170                 for (i = 0;i < r_refdef.scene.numentities;i++)
5171                 {
5172                         ent = r_refdef.scene.entities[i];
5173                         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));
5174                 }
5175         }
5176         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5177                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5178         {
5179                 for (i = 0;i < r_refdef.scene.numentities;i++)
5180                 {
5181                         if (!r_refdef.viewcache.entityvisible[i])
5182                                 continue;
5183                         ent = r_refdef.scene.entities[i];
5184                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5185                         {
5186                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5187                                 if (samples < 0)
5188                                         continue; // temp entities do pvs only
5189                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5190                                         ent->last_trace_visibility = realtime;
5191                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5192                                         r_refdef.viewcache.entityvisible[i] = 0;
5193                         }
5194                 }
5195         }
5196 }
5197
5198 /// only used if skyrendermasked, and normally returns false
5199 static int R_DrawBrushModelsSky (void)
5200 {
5201         int i, sky;
5202         entity_render_t *ent;
5203
5204         sky = false;
5205         for (i = 0;i < r_refdef.scene.numentities;i++)
5206         {
5207                 if (!r_refdef.viewcache.entityvisible[i])
5208                         continue;
5209                 ent = r_refdef.scene.entities[i];
5210                 if (!ent->model || !ent->model->DrawSky)
5211                         continue;
5212                 ent->model->DrawSky(ent);
5213                 sky = true;
5214         }
5215         return sky;
5216 }
5217
5218 static void R_DrawNoModel(entity_render_t *ent);
5219 static void R_DrawModels(void)
5220 {
5221         int i;
5222         entity_render_t *ent;
5223
5224         for (i = 0;i < r_refdef.scene.numentities;i++)
5225         {
5226                 if (!r_refdef.viewcache.entityvisible[i])
5227                         continue;
5228                 ent = r_refdef.scene.entities[i];
5229                 r_refdef.stats[r_stat_entities]++;
5230                 /*
5231                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5232                 {
5233                         vec3_t f, l, u, o;
5234                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5235                         Con_Printf("R_DrawModels\n");
5236                         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]);
5237                         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);
5238                         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);
5239                 }
5240                 */
5241                 if (ent->model && ent->model->Draw != NULL)
5242                         ent->model->Draw(ent);
5243                 else
5244                         R_DrawNoModel(ent);
5245         }
5246 }
5247
5248 static void R_DrawModelsDepth(void)
5249 {
5250         int i;
5251         entity_render_t *ent;
5252
5253         for (i = 0;i < r_refdef.scene.numentities;i++)
5254         {
5255                 if (!r_refdef.viewcache.entityvisible[i])
5256                         continue;
5257                 ent = r_refdef.scene.entities[i];
5258                 if (ent->model && ent->model->DrawDepth != NULL)
5259                         ent->model->DrawDepth(ent);
5260         }
5261 }
5262
5263 static void R_DrawModelsDebug(void)
5264 {
5265         int i;
5266         entity_render_t *ent;
5267
5268         for (i = 0;i < r_refdef.scene.numentities;i++)
5269         {
5270                 if (!r_refdef.viewcache.entityvisible[i])
5271                         continue;
5272                 ent = r_refdef.scene.entities[i];
5273                 if (ent->model && ent->model->DrawDebug != NULL)
5274                         ent->model->DrawDebug(ent);
5275         }
5276 }
5277
5278 static void R_DrawModelsAddWaterPlanes(void)
5279 {
5280         int i;
5281         entity_render_t *ent;
5282
5283         for (i = 0;i < r_refdef.scene.numentities;i++)
5284         {
5285                 if (!r_refdef.viewcache.entityvisible[i])
5286                         continue;
5287                 ent = r_refdef.scene.entities[i];
5288                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5289                         ent->model->DrawAddWaterPlanes(ent);
5290         }
5291 }
5292
5293 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}};
5294
5295 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5296 {
5297         if (r_hdr_irisadaptation.integer)
5298         {
5299                 vec3_t p;
5300                 vec3_t ambient;
5301                 vec3_t diffuse;
5302                 vec3_t diffusenormal;
5303                 vec3_t forward;
5304                 vec_t brightness = 0.0f;
5305                 vec_t goal;
5306                 vec_t current;
5307                 vec_t d;
5308                 int c;
5309                 VectorCopy(r_refdef.view.forward, forward);
5310                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5311                 {
5312                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5313                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5314                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5315                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5316                         d = DotProduct(forward, diffusenormal);
5317                         brightness += VectorLength(ambient);
5318                         if (d > 0)
5319                                 brightness += d * VectorLength(diffuse);
5320                 }
5321                 brightness *= 1.0f / c;
5322                 brightness += 0.00001f; // make sure it's never zero
5323                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5324                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5325                 current = r_hdr_irisadaptation_value.value;
5326                 if (current < goal)
5327                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5328                 else if (current > goal)
5329                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5330                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5331                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5332         }
5333         else if (r_hdr_irisadaptation_value.value != 1.0f)
5334                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5335 }
5336
5337 static void R_View_SetFrustum(const int *scissor)
5338 {
5339         int i;
5340         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5341         vec3_t forward, left, up, origin, v;
5342
5343         if(scissor)
5344         {
5345                 // flipped x coordinates (because x points left here)
5346                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5347                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5348
5349                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5350                 switch(vid.renderpath)
5351                 {
5352                         case RENDERPATH_D3D9:
5353                         case RENDERPATH_D3D10:
5354                         case RENDERPATH_D3D11:
5355                                 // non-flipped y coordinates
5356                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5357                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5358                                 break;
5359                         case RENDERPATH_SOFT:
5360                         case RENDERPATH_GL11:
5361                         case RENDERPATH_GL13:
5362                         case RENDERPATH_GL20:
5363                         case RENDERPATH_GLES1:
5364                         case RENDERPATH_GLES2:
5365                                 // non-flipped y coordinates
5366                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5367                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5368                                 break;
5369                 }
5370         }
5371
5372         // we can't trust r_refdef.view.forward and friends in reflected scenes
5373         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5374
5375 #if 0
5376         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5377         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5378         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5379         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5380         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5381         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5382         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5383         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5384         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5385         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5386         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5387         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5388 #endif
5389
5390 #if 0
5391         zNear = r_refdef.nearclip;
5392         nudge = 1.0 - 1.0 / (1<<23);
5393         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5394         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5395         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5396         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5397         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5398         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5399         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5400         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5401 #endif
5402
5403
5404
5405 #if 0
5406         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5407         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5408         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5409         r_refdef.view.frustum[0].dist = m[15] - m[12];
5410
5411         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5412         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5413         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5414         r_refdef.view.frustum[1].dist = m[15] + m[12];
5415
5416         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5417         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5418         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5419         r_refdef.view.frustum[2].dist = m[15] - m[13];
5420
5421         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5422         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5423         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5424         r_refdef.view.frustum[3].dist = m[15] + m[13];
5425
5426         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5427         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5428         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5429         r_refdef.view.frustum[4].dist = m[15] - m[14];
5430
5431         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5432         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5433         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5434         r_refdef.view.frustum[5].dist = m[15] + m[14];
5435 #endif
5436
5437         if (r_refdef.view.useperspective)
5438         {
5439                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5440                 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]);
5441                 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]);
5442                 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]);
5443                 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]);
5444
5445                 // then the normals from the corners relative to origin
5446                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5447                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5448                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5449                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5450
5451                 // in a NORMAL view, forward cross left == up
5452                 // in a REFLECTED view, forward cross left == down
5453                 // so our cross products above need to be adjusted for a left handed coordinate system
5454                 CrossProduct(forward, left, v);
5455                 if(DotProduct(v, up) < 0)
5456                 {
5457                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5458                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5459                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5460                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5461                 }
5462
5463                 // Leaving those out was a mistake, those were in the old code, and they
5464                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5465                 // I couldn't reproduce it after adding those normalizations. --blub
5466                 VectorNormalize(r_refdef.view.frustum[0].normal);
5467                 VectorNormalize(r_refdef.view.frustum[1].normal);
5468                 VectorNormalize(r_refdef.view.frustum[2].normal);
5469                 VectorNormalize(r_refdef.view.frustum[3].normal);
5470
5471                 // make the corners absolute
5472                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5473                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5474                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5475                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5476
5477                 // one more normal
5478                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5479
5480                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5481                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5482                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5483                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5484                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5485         }
5486         else
5487         {
5488                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5489                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5490                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5491                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5492                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5493                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5494                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5495                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5496                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5497                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5498         }
5499         r_refdef.view.numfrustumplanes = 5;
5500
5501         if (r_refdef.view.useclipplane)
5502         {
5503                 r_refdef.view.numfrustumplanes = 6;
5504                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5505         }
5506
5507         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5508                 PlaneClassify(r_refdef.view.frustum + i);
5509
5510         // LordHavoc: note to all quake engine coders, Quake had a special case
5511         // for 90 degrees which assumed a square view (wrong), so I removed it,
5512         // Quake2 has it disabled as well.
5513
5514         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5515         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5516         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5517         //PlaneClassify(&frustum[0]);
5518
5519         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5520         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5521         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5522         //PlaneClassify(&frustum[1]);
5523
5524         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5525         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5526         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5527         //PlaneClassify(&frustum[2]);
5528
5529         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5530         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5531         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5532         //PlaneClassify(&frustum[3]);
5533
5534         // nearclip plane
5535         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5536         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5537         //PlaneClassify(&frustum[4]);
5538 }
5539
5540 static void R_View_UpdateWithScissor(const int *myscissor)
5541 {
5542         R_Main_ResizeViewCache();
5543         R_View_SetFrustum(myscissor);
5544         R_View_WorldVisibility(r_refdef.view.useclipplane);
5545         R_View_UpdateEntityVisible();
5546         R_View_UpdateEntityLighting();
5547 }
5548
5549 static void R_View_Update(void)
5550 {
5551         R_Main_ResizeViewCache();
5552         R_View_SetFrustum(NULL);
5553         R_View_WorldVisibility(r_refdef.view.useclipplane);
5554         R_View_UpdateEntityVisible();
5555         R_View_UpdateEntityLighting();
5556 }
5557
5558 float viewscalefpsadjusted = 1.0f;
5559
5560 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5561 {
5562         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5563         scale = bound(0.03125f, scale, 1.0f);
5564         *outwidth = (int)ceil(width * scale);
5565         *outheight = (int)ceil(height * scale);
5566 }
5567
5568 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5569 {
5570         const float *customclipplane = NULL;
5571         float plane[4];
5572         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5573         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5574         {
5575                 // LordHavoc: couldn't figure out how to make this approach the
5576                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5577                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5578                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5579                         dist = r_refdef.view.clipplane.dist;
5580                 plane[0] = r_refdef.view.clipplane.normal[0];
5581                 plane[1] = r_refdef.view.clipplane.normal[1];
5582                 plane[2] = r_refdef.view.clipplane.normal[2];
5583                 plane[3] = -dist;
5584                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5585         }
5586
5587         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5588         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5589
5590         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5591         if (!r_refdef.view.useperspective)
5592                 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);
5593         else if (vid.stencil && r_useinfinitefarclip.integer)
5594                 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);
5595         else
5596                 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);
5597         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5598         R_SetViewport(&r_refdef.view.viewport);
5599         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5600         {
5601                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5602                 float screenplane[4];
5603                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5604                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5605                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5606                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5607                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5608         }
5609 }
5610
5611 void R_EntityMatrix(const matrix4x4_t *matrix)
5612 {
5613         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5614         {
5615                 gl_modelmatrixchanged = false;
5616                 gl_modelmatrix = *matrix;
5617                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5618                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5619                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5620                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5621                 CHECKGLERROR
5622                 switch(vid.renderpath)
5623                 {
5624                 case RENDERPATH_D3D9:
5625 #ifdef SUPPORTD3D
5626                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5627                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5628 #endif
5629                         break;
5630                 case RENDERPATH_D3D10:
5631                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5632                         break;
5633                 case RENDERPATH_D3D11:
5634                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5635                         break;
5636                 case RENDERPATH_GL11:
5637                 case RENDERPATH_GL13:
5638                 case RENDERPATH_GLES1:
5639                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5640                         break;
5641                 case RENDERPATH_SOFT:
5642                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5643                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5644                         break;
5645                 case RENDERPATH_GL20:
5646                 case RENDERPATH_GLES2:
5647                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5648                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5649                         break;
5650                 }
5651         }
5652 }
5653
5654 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5655 {
5656         r_viewport_t viewport;
5657
5658         CHECKGLERROR
5659
5660         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5661         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);
5662         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5663         R_SetViewport(&viewport);
5664         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5665         GL_Color(1, 1, 1, 1);
5666         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5667         GL_BlendFunc(GL_ONE, GL_ZERO);
5668         GL_ScissorTest(false);
5669         GL_DepthMask(false);
5670         GL_DepthRange(0, 1);
5671         GL_DepthTest(false);
5672         GL_DepthFunc(GL_LEQUAL);
5673         R_EntityMatrix(&identitymatrix);
5674         R_Mesh_ResetTextureState();
5675         GL_PolygonOffset(0, 0);
5676         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5677         switch(vid.renderpath)
5678         {
5679         case RENDERPATH_GL11:
5680         case RENDERPATH_GL13:
5681         case RENDERPATH_GL20:
5682         case RENDERPATH_GLES1:
5683         case RENDERPATH_GLES2:
5684                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5685                 break;
5686         case RENDERPATH_D3D9:
5687         case RENDERPATH_D3D10:
5688         case RENDERPATH_D3D11:
5689         case RENDERPATH_SOFT:
5690                 break;
5691         }
5692         GL_CullFace(GL_NONE);
5693
5694         CHECKGLERROR
5695 }
5696
5697 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5698 {
5699         DrawQ_Finish();
5700
5701         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5702 }
5703
5704 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5705 {
5706         DrawQ_Finish();
5707
5708         R_SetupView(true, fbo, depthtexture, colortexture);
5709         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5710         GL_Color(1, 1, 1, 1);
5711         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5712         GL_BlendFunc(GL_ONE, GL_ZERO);
5713         GL_ScissorTest(true);
5714         GL_DepthMask(true);
5715         GL_DepthRange(0, 1);
5716         GL_DepthTest(true);
5717         GL_DepthFunc(GL_LEQUAL);
5718         R_EntityMatrix(&identitymatrix);
5719         R_Mesh_ResetTextureState();
5720         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5721         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5722         switch(vid.renderpath)
5723         {
5724         case RENDERPATH_GL11:
5725         case RENDERPATH_GL13:
5726         case RENDERPATH_GL20:
5727         case RENDERPATH_GLES1:
5728         case RENDERPATH_GLES2:
5729                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5730                 break;
5731         case RENDERPATH_D3D9:
5732         case RENDERPATH_D3D10:
5733         case RENDERPATH_D3D11:
5734         case RENDERPATH_SOFT:
5735                 break;
5736         }
5737         GL_CullFace(r_refdef.view.cullface_back);
5738 }
5739
5740 /*
5741 ================
5742 R_RenderView_UpdateViewVectors
5743 ================
5744 */
5745 void R_RenderView_UpdateViewVectors(void)
5746 {
5747         // break apart the view matrix into vectors for various purposes
5748         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5749         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5750         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5751         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5752         // make an inverted copy of the view matrix for tracking sprites
5753         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5754 }
5755
5756 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5757 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5758
5759 static void R_Water_StartFrame(void)
5760 {
5761         int i;
5762         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5763         r_waterstate_waterplane_t *p;
5764         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;
5765
5766         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5767                 return;
5768
5769         switch(vid.renderpath)
5770         {
5771         case RENDERPATH_GL20:
5772         case RENDERPATH_D3D9:
5773         case RENDERPATH_D3D10:
5774         case RENDERPATH_D3D11:
5775         case RENDERPATH_SOFT:
5776         case RENDERPATH_GLES2:
5777                 break;
5778         case RENDERPATH_GL11:
5779         case RENDERPATH_GL13:
5780         case RENDERPATH_GLES1:
5781                 return;
5782         }
5783
5784         // set waterwidth and waterheight to the water resolution that will be
5785         // used (often less than the screen resolution for faster rendering)
5786         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5787
5788         // calculate desired texture sizes
5789         // can't use water if the card does not support the texture size
5790         if (!r_water.integer || r_showsurfaces.integer)
5791                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5792         else if (vid.support.arb_texture_non_power_of_two)
5793         {
5794                 texturewidth = waterwidth;
5795                 textureheight = waterheight;
5796                 camerawidth = waterwidth;
5797                 cameraheight = waterheight;
5798         }
5799         else
5800         {
5801                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5802                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5803                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5804                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5805         }
5806
5807         // allocate textures as needed
5808         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))
5809         {
5810                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5811                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5812                 {
5813                         if (p->texture_refraction)
5814                                 R_FreeTexture(p->texture_refraction);
5815                         p->texture_refraction = NULL;
5816                         if (p->fbo_refraction)
5817                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5818                         p->fbo_refraction = 0;
5819                         if (p->texture_reflection)
5820                                 R_FreeTexture(p->texture_reflection);
5821                         p->texture_reflection = NULL;
5822                         if (p->fbo_reflection)
5823                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5824                         p->fbo_reflection = 0;
5825                         if (p->texture_camera)
5826                                 R_FreeTexture(p->texture_camera);
5827                         p->texture_camera = NULL;
5828                         if (p->fbo_camera)
5829                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5830                         p->fbo_camera = 0;
5831                 }
5832                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5833                 r_fb.water.texturewidth = texturewidth;
5834                 r_fb.water.textureheight = textureheight;
5835                 r_fb.water.camerawidth = camerawidth;
5836                 r_fb.water.cameraheight = cameraheight;
5837         }
5838
5839         if (r_fb.water.texturewidth)
5840         {
5841                 int scaledwidth, scaledheight;
5842
5843                 r_fb.water.enabled = true;
5844
5845                 // water resolution is usually reduced
5846                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5847                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5848                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5849
5850                 // set up variables that will be used in shader setup
5851                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5852                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5853                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5854                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5855         }
5856
5857         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5858         r_fb.water.numwaterplanes = 0;
5859 }
5860
5861 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5862 {
5863         int planeindex, bestplaneindex, vertexindex;
5864         vec3_t mins, maxs, normal, center, v, n;
5865         vec_t planescore, bestplanescore;
5866         mplane_t plane;
5867         r_waterstate_waterplane_t *p;
5868         texture_t *t = R_GetCurrentTexture(surface->texture);
5869
5870         rsurface.texture = t;
5871         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5872         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5873         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5874                 return;
5875         // average the vertex normals, find the surface bounds (after deformvertexes)
5876         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5877         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5878         VectorCopy(n, normal);
5879         VectorCopy(v, mins);
5880         VectorCopy(v, maxs);
5881         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5882         {
5883                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5884                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5885                 VectorAdd(normal, n, normal);
5886                 mins[0] = min(mins[0], v[0]);
5887                 mins[1] = min(mins[1], v[1]);
5888                 mins[2] = min(mins[2], v[2]);
5889                 maxs[0] = max(maxs[0], v[0]);
5890                 maxs[1] = max(maxs[1], v[1]);
5891                 maxs[2] = max(maxs[2], v[2]);
5892         }
5893         VectorNormalize(normal);
5894         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5895
5896         VectorCopy(normal, plane.normal);
5897         VectorNormalize(plane.normal);
5898         plane.dist = DotProduct(center, plane.normal);
5899         PlaneClassify(&plane);
5900         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5901         {
5902                 // skip backfaces (except if nocullface is set)
5903 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5904 //                      return;
5905                 VectorNegate(plane.normal, plane.normal);
5906                 plane.dist *= -1;
5907                 PlaneClassify(&plane);
5908         }
5909
5910
5911         // find a matching plane if there is one
5912         bestplaneindex = -1;
5913         bestplanescore = 1048576.0f;
5914         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5915         {
5916                 if(p->camera_entity == t->camera_entity)
5917                 {
5918                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5919                         if (bestplaneindex < 0 || bestplanescore > planescore)
5920                         {
5921                                 bestplaneindex = planeindex;
5922                                 bestplanescore = planescore;
5923                         }
5924                 }
5925         }
5926         planeindex = bestplaneindex;
5927         p = r_fb.water.waterplanes + planeindex;
5928
5929         // if this surface does not fit any known plane rendered this frame, add one
5930         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5931         {
5932                 // store the new plane
5933                 planeindex = r_fb.water.numwaterplanes++;
5934                 p = r_fb.water.waterplanes + planeindex;
5935                 p->plane = plane;
5936                 // clear materialflags and pvs
5937                 p->materialflags = 0;
5938                 p->pvsvalid = false;
5939                 p->camera_entity = t->camera_entity;
5940                 VectorCopy(mins, p->mins);
5941                 VectorCopy(maxs, p->maxs);
5942         }
5943         else
5944         {
5945                 // merge mins/maxs when we're adding this surface to the plane
5946                 p->mins[0] = min(p->mins[0], mins[0]);
5947                 p->mins[1] = min(p->mins[1], mins[1]);
5948                 p->mins[2] = min(p->mins[2], mins[2]);
5949                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5950                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5951                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5952         }
5953         // merge this surface's materialflags into the waterplane
5954         p->materialflags |= t->currentmaterialflags;
5955         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5956         {
5957                 // merge this surface's PVS into the waterplane
5958                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5959                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5960                 {
5961                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5962                         p->pvsvalid = true;
5963                 }
5964         }
5965 }
5966
5967 extern cvar_t r_drawparticles;
5968 extern cvar_t r_drawdecals;
5969
5970 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5971 {
5972         int myscissor[4];
5973         r_refdef_view_t originalview;
5974         r_refdef_view_t myview;
5975         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;
5976         r_waterstate_waterplane_t *p;
5977         vec3_t visorigin;
5978         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;
5979         char vabuf[1024];
5980
5981         originalview = r_refdef.view;
5982
5983         // lowquality hack, temporarily shut down some cvars and restore afterwards
5984         qualityreduction = r_water_lowquality.integer;
5985         if (qualityreduction > 0)
5986         {
5987                 if (qualityreduction >= 1)
5988                 {
5989                         old_r_shadows = r_shadows.integer;
5990                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5991                         old_r_dlight = r_shadow_realtime_dlight.integer;
5992                         Cvar_SetValueQuick(&r_shadows, 0);
5993                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5994                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5995                 }
5996                 if (qualityreduction >= 2)
5997                 {
5998                         old_r_dynamic = r_dynamic.integer;
5999                         old_r_particles = r_drawparticles.integer;
6000                         old_r_decals = r_drawdecals.integer;
6001                         Cvar_SetValueQuick(&r_dynamic, 0);
6002                         Cvar_SetValueQuick(&r_drawparticles, 0);
6003                         Cvar_SetValueQuick(&r_drawdecals, 0);
6004                 }
6005         }
6006
6007         // make sure enough textures are allocated
6008         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6009         {
6010                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6011                 {
6012                         if (!p->texture_refraction)
6013                                 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);
6014                         if (!p->texture_refraction)
6015                                 goto error;
6016                         if (usewaterfbo)
6017                         {
6018                                 if (r_fb.water.depthtexture == NULL)
6019                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6020                                 if (p->fbo_refraction == 0)
6021                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6022                         }
6023                 }
6024                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6025                 {
6026                         if (!p->texture_camera)
6027                                 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);
6028                         if (!p->texture_camera)
6029                                 goto error;
6030                         if (usewaterfbo)
6031                         {
6032                                 if (r_fb.water.depthtexture == NULL)
6033                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6034                                 if (p->fbo_camera == 0)
6035                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6036                         }
6037                 }
6038
6039                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6040                 {
6041                         if (!p->texture_reflection)
6042                                 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);
6043                         if (!p->texture_reflection)
6044                                 goto error;
6045                         if (usewaterfbo)
6046                         {
6047                                 if (r_fb.water.depthtexture == NULL)
6048                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6049                                 if (p->fbo_reflection == 0)
6050                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6051                         }
6052                 }
6053         }
6054
6055         // render views
6056         r_refdef.view = originalview;
6057         r_refdef.view.showdebug = false;
6058         r_refdef.view.width = r_fb.water.waterwidth;
6059         r_refdef.view.height = r_fb.water.waterheight;
6060         r_refdef.view.useclipplane = true;
6061         myview = r_refdef.view;
6062         r_fb.water.renderingscene = true;
6063         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6064         {
6065                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6066                 {
6067                         r_refdef.view = myview;
6068                         if(r_water_scissormode.integer)
6069                         {
6070                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6071                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6072                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6073                         }
6074
6075                         // render reflected scene and copy into texture
6076                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6077                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6078                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6079                         r_refdef.view.clipplane = p->plane;
6080                         // reverse the cullface settings for this render
6081                         r_refdef.view.cullface_front = GL_FRONT;
6082                         r_refdef.view.cullface_back = GL_BACK;
6083                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6084                         {
6085                                 r_refdef.view.usecustompvs = true;
6086                                 if (p->pvsvalid)
6087                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6088                                 else
6089                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6090                         }
6091
6092                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
6093                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6094                         R_ClearScreen(r_refdef.fogenabled);
6095                         if(r_water_scissormode.integer & 2)
6096                                 R_View_UpdateWithScissor(myscissor);
6097                         else
6098                                 R_View_Update();
6099                         R_AnimCache_CacheVisibleEntities();
6100                         if(r_water_scissormode.integer & 1)
6101                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6102                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6103
6104                         if (!p->fbo_reflection)
6105                                 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);
6106                         r_fb.water.hideplayer = false;
6107                 }
6108
6109                 // render the normal view scene and copy into texture
6110                 // (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)
6111                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6112                 {
6113                         r_refdef.view = myview;
6114                         if(r_water_scissormode.integer)
6115                         {
6116                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6117                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6118                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6119                         }
6120
6121                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6122
6123                         r_refdef.view.clipplane = p->plane;
6124                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6125                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6126
6127                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6128                         {
6129                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6130                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6131                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6132                                 R_RenderView_UpdateViewVectors();
6133                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6134                                 {
6135                                         r_refdef.view.usecustompvs = true;
6136                                         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);
6137                                 }
6138                         }
6139
6140                         PlaneClassify(&r_refdef.view.clipplane);
6141
6142                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6143                         R_ClearScreen(r_refdef.fogenabled);
6144                         if(r_water_scissormode.integer & 2)
6145                                 R_View_UpdateWithScissor(myscissor);
6146                         else
6147                                 R_View_Update();
6148                         R_AnimCache_CacheVisibleEntities();
6149                         if(r_water_scissormode.integer & 1)
6150                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6151                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6152
6153                         if (!p->fbo_refraction)
6154                                 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);
6155                         r_fb.water.hideplayer = false;
6156                 }
6157                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6158                 {
6159                         r_refdef.view = myview;
6160
6161                         r_refdef.view.clipplane = p->plane;
6162                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6163                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6164
6165                         r_refdef.view.width = r_fb.water.camerawidth;
6166                         r_refdef.view.height = r_fb.water.cameraheight;
6167                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6168                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6169                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6170                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6171
6172                         if(p->camera_entity)
6173                         {
6174                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6175                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6176                         }
6177
6178                         // note: all of the view is used for displaying... so
6179                         // there is no use in scissoring
6180
6181                         // reverse the cullface settings for this render
6182                         r_refdef.view.cullface_front = GL_FRONT;
6183                         r_refdef.view.cullface_back = GL_BACK;
6184                         // also reverse the view matrix
6185                         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
6186                         R_RenderView_UpdateViewVectors();
6187                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6188                         {
6189                                 r_refdef.view.usecustompvs = true;
6190                                 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);
6191                         }
6192                         
6193                         // camera needs no clipplane
6194                         r_refdef.view.useclipplane = false;
6195
6196                         PlaneClassify(&r_refdef.view.clipplane);
6197
6198                         r_fb.water.hideplayer = false;
6199
6200                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6201                         R_ClearScreen(r_refdef.fogenabled);
6202                         R_View_Update();
6203                         R_AnimCache_CacheVisibleEntities();
6204                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6205
6206                         if (!p->fbo_camera)
6207                                 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);
6208                         r_fb.water.hideplayer = false;
6209                 }
6210
6211         }
6212         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6213         r_fb.water.renderingscene = false;
6214         r_refdef.view = originalview;
6215         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6216         if (!r_fb.water.depthtexture)
6217                 R_ClearScreen(r_refdef.fogenabled);
6218         R_View_Update();
6219         R_AnimCache_CacheVisibleEntities();
6220         goto finish;
6221 error:
6222         r_refdef.view = originalview;
6223         r_fb.water.renderingscene = false;
6224         Cvar_SetValueQuick(&r_water, 0);
6225         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6226 finish:
6227         // lowquality hack, restore cvars
6228         if (qualityreduction > 0)
6229         {
6230                 if (qualityreduction >= 1)
6231                 {
6232                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6233                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6234                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6235                 }
6236                 if (qualityreduction >= 2)
6237                 {
6238                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6239                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6240                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6241                 }
6242         }
6243 }
6244
6245 static void R_Bloom_StartFrame(void)
6246 {
6247         int i;
6248         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6249         int viewwidth, viewheight;
6250         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6251         textype_t textype = TEXTYPE_COLORBUFFER;
6252
6253         switch (vid.renderpath)
6254         {
6255         case RENDERPATH_GL20:
6256                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6257                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6258                 {
6259                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6260                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6261                 }
6262                 break;
6263         case RENDERPATH_GL11:
6264         case RENDERPATH_GL13:
6265         case RENDERPATH_GLES1:
6266         case RENDERPATH_GLES2:
6267         case RENDERPATH_D3D9:
6268         case RENDERPATH_D3D10:
6269         case RENDERPATH_D3D11:
6270                 r_fb.usedepthtextures = false;
6271                 break;
6272         case RENDERPATH_SOFT:
6273                 r_fb.usedepthtextures = true;
6274                 break;
6275         }
6276
6277         if (r_viewscale_fpsscaling.integer)
6278         {
6279                 double actualframetime;
6280                 double targetframetime;
6281                 double adjust;
6282                 actualframetime = r_refdef.lastdrawscreentime;
6283                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6284                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6285                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6286                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6287                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6288                 viewscalefpsadjusted += adjust;
6289                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6290         }
6291         else
6292                 viewscalefpsadjusted = 1.0f;
6293
6294         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6295
6296         switch(vid.renderpath)
6297         {
6298         case RENDERPATH_GL20:
6299         case RENDERPATH_D3D9:
6300         case RENDERPATH_D3D10:
6301         case RENDERPATH_D3D11:
6302         case RENDERPATH_SOFT:
6303         case RENDERPATH_GLES2:
6304                 break;
6305         case RENDERPATH_GL11:
6306         case RENDERPATH_GL13:
6307         case RENDERPATH_GLES1:
6308                 return;
6309         }
6310
6311         // set bloomwidth and bloomheight to the bloom resolution that will be
6312         // used (often less than the screen resolution for faster rendering)
6313         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6314         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6315         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6316         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6317         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6318
6319         // calculate desired texture sizes
6320         if (vid.support.arb_texture_non_power_of_two)
6321         {
6322                 screentexturewidth = vid.width;
6323                 screentextureheight = vid.height;
6324                 bloomtexturewidth = r_fb.bloomwidth;
6325                 bloomtextureheight = r_fb.bloomheight;
6326         }
6327         else
6328         {
6329                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6330                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6331                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6332                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6333         }
6334
6335         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))
6336         {
6337                 Cvar_SetValueQuick(&r_bloom, 0);
6338                 Cvar_SetValueQuick(&r_motionblur, 0);
6339                 Cvar_SetValueQuick(&r_damageblur, 0);
6340         }
6341
6342         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6343          && !r_bloom.integer
6344          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6345          && !useviewfbo
6346          && r_viewscale.value == 1.0f
6347          && !r_viewscale_fpsscaling.integer)
6348                 screentexturewidth = screentextureheight = 0;
6349         if (!r_bloom.integer)
6350                 bloomtexturewidth = bloomtextureheight = 0;
6351
6352         // allocate textures as needed
6353         if (r_fb.screentexturewidth != screentexturewidth
6354          || r_fb.screentextureheight != screentextureheight
6355          || r_fb.bloomtexturewidth != bloomtexturewidth
6356          || r_fb.bloomtextureheight != bloomtextureheight
6357          || r_fb.textype != textype
6358          || useviewfbo != (r_fb.fbo != 0))
6359         {
6360                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6361                 {
6362                         if (r_fb.bloomtexture[i])
6363                                 R_FreeTexture(r_fb.bloomtexture[i]);
6364                         r_fb.bloomtexture[i] = NULL;
6365
6366                         if (r_fb.bloomfbo[i])
6367                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6368                         r_fb.bloomfbo[i] = 0;
6369                 }
6370
6371                 if (r_fb.fbo)
6372                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6373                 r_fb.fbo = 0;
6374
6375                 if (r_fb.colortexture)
6376                         R_FreeTexture(r_fb.colortexture);
6377                 r_fb.colortexture = NULL;
6378
6379                 if (r_fb.depthtexture)
6380                         R_FreeTexture(r_fb.depthtexture);
6381                 r_fb.depthtexture = NULL;
6382
6383                 if (r_fb.ghosttexture)
6384                         R_FreeTexture(r_fb.ghosttexture);
6385                 r_fb.ghosttexture = NULL;
6386
6387                 r_fb.screentexturewidth = screentexturewidth;
6388                 r_fb.screentextureheight = screentextureheight;
6389                 r_fb.bloomtexturewidth = bloomtexturewidth;
6390                 r_fb.bloomtextureheight = bloomtextureheight;
6391                 r_fb.textype = textype;
6392
6393                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6394                 {
6395                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6396                                 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);
6397                         r_fb.ghosttexture_valid = false;
6398                         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);
6399                         if (useviewfbo)
6400                         {
6401                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6402                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6403                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6404                         }
6405                 }
6406
6407                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6408                 {
6409                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6410                         {
6411                                 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);
6412                                 if (useviewfbo)
6413                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6414                         }
6415                 }
6416         }
6417
6418         // bloom texture is a different resolution
6419         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6420         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6421         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6422         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6423         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6424
6425         // set up a texcoord array for the full resolution screen image
6426         // (we have to keep this around to copy back during final render)
6427         r_fb.screentexcoord2f[0] = 0;
6428         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6429         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6430         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6431         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6432         r_fb.screentexcoord2f[5] = 0;
6433         r_fb.screentexcoord2f[6] = 0;
6434         r_fb.screentexcoord2f[7] = 0;
6435
6436         if(r_fb.fbo) 
6437         {
6438                 for (i = 1;i < 8;i += 2)
6439                 {
6440                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6441                 }
6442         }
6443
6444         // set up a texcoord array for the reduced resolution bloom image
6445         // (which will be additive blended over the screen image)
6446         r_fb.bloomtexcoord2f[0] = 0;
6447         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6448         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6449         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6450         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6451         r_fb.bloomtexcoord2f[5] = 0;
6452         r_fb.bloomtexcoord2f[6] = 0;
6453         r_fb.bloomtexcoord2f[7] = 0;
6454
6455         switch(vid.renderpath)
6456         {
6457         case RENDERPATH_GL11:
6458         case RENDERPATH_GL13:
6459         case RENDERPATH_GL20:
6460         case RENDERPATH_SOFT:
6461         case RENDERPATH_GLES1:
6462         case RENDERPATH_GLES2:
6463                 break;
6464         case RENDERPATH_D3D9:
6465         case RENDERPATH_D3D10:
6466         case RENDERPATH_D3D11:
6467                 for (i = 0;i < 4;i++)
6468                 {
6469                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6470                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6471                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6472                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6473                 }
6474                 break;
6475         }
6476
6477         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6478
6479         if (r_fb.fbo)
6480                 r_refdef.view.clear = true;
6481 }
6482
6483 static void R_Bloom_MakeTexture(void)
6484 {
6485         int x, range, dir;
6486         float xoffset, yoffset, r, brighten;
6487         rtexture_t *intex;
6488         float colorscale = r_bloom_colorscale.value;
6489
6490         r_refdef.stats[r_stat_bloom]++;
6491     
6492 #if 0
6493     // this copy is unnecessary since it happens in R_BlendView already
6494         if (!r_fb.fbo)
6495         {
6496                 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);
6497                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6498         }
6499 #endif
6500
6501         // scale down screen texture to the bloom texture size
6502         CHECKGLERROR
6503         r_fb.bloomindex = 0;
6504         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6505         R_SetViewport(&r_fb.bloomviewport);
6506         GL_DepthTest(false);
6507         GL_BlendFunc(GL_ONE, GL_ZERO);
6508         GL_Color(colorscale, colorscale, colorscale, 1);
6509         // 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...
6510         switch(vid.renderpath)
6511         {
6512         case RENDERPATH_GL11:
6513         case RENDERPATH_GL13:
6514         case RENDERPATH_GL20:
6515         case RENDERPATH_GLES1:
6516         case RENDERPATH_GLES2:
6517         case RENDERPATH_SOFT:
6518                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6519                 break;
6520         case RENDERPATH_D3D9:
6521         case RENDERPATH_D3D10:
6522         case RENDERPATH_D3D11:
6523                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6524                 break;
6525         }
6526         // TODO: do boxfilter scale-down in shader?
6527         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6528         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6529         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6530
6531         // we now have a properly scaled bloom image
6532         if (!r_fb.bloomfbo[r_fb.bloomindex])
6533         {
6534                 // copy it into the bloom texture
6535                 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);
6536                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6537         }
6538
6539         // multiply bloom image by itself as many times as desired
6540         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6541         {
6542                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6543                 r_fb.bloomindex ^= 1;
6544                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6545                 x *= 2;
6546                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6547                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6548                 {
6549                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6550                         GL_Color(r,r,r,1); // apply fix factor
6551                 }
6552                 else
6553                 {
6554                         if(x <= 2)
6555                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6556                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6557                         GL_Color(1,1,1,1); // no fix factor supported here
6558                 }
6559                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6560                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6561                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6562                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6563
6564                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6565                 {
6566                         // copy the darkened image to a texture
6567                         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);
6568                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6569                 }
6570         }
6571
6572         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6573         brighten = r_bloom_brighten.value;
6574         brighten = sqrt(brighten);
6575         if(range >= 1)
6576                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6577
6578         for (dir = 0;dir < 2;dir++)
6579         {
6580                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6581                 r_fb.bloomindex ^= 1;
6582                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6583                 // blend on at multiple vertical offsets to achieve a vertical blur
6584                 // TODO: do offset blends using GLSL
6585                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6586                 GL_BlendFunc(GL_ONE, GL_ZERO);
6587                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6588                 for (x = -range;x <= range;x++)
6589                 {
6590                         if (!dir){xoffset = 0;yoffset = x;}
6591                         else {xoffset = x;yoffset = 0;}
6592                         xoffset /= (float)r_fb.bloomtexturewidth;
6593                         yoffset /= (float)r_fb.bloomtextureheight;
6594                         // compute a texcoord array with the specified x and y offset
6595                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6596                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6597                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6598                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6599                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6600                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6601                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6602                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6603                         // this r value looks like a 'dot' particle, fading sharply to
6604                         // black at the edges
6605                         // (probably not realistic but looks good enough)
6606                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6607                         //r = brighten/(range*2+1);
6608                         r = brighten / (range * 2 + 1);
6609                         if(range >= 1)
6610                                 r *= (1 - x*x/(float)(range*range));
6611                         GL_Color(r, r, r, 1);
6612                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6613                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6614                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6615                         GL_BlendFunc(GL_ONE, GL_ONE);
6616                 }
6617
6618                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6619                 {
6620                         // copy the vertically or horizontally blurred bloom view to a texture
6621                         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);
6622                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6623                 }
6624         }
6625 }
6626
6627 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6628 {
6629         unsigned int permutation;
6630         float uservecs[4][4];
6631
6632         R_EntityMatrix(&identitymatrix);
6633
6634         switch (vid.renderpath)
6635         {
6636         case RENDERPATH_GL20:
6637         case RENDERPATH_D3D9:
6638         case RENDERPATH_D3D10:
6639         case RENDERPATH_D3D11:
6640         case RENDERPATH_SOFT:
6641         case RENDERPATH_GLES2:
6642                 permutation =
6643                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6644                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6645                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6646                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6647                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6648
6649                 if (r_fb.colortexture)
6650                 {
6651                         if (!r_fb.fbo)
6652                         {
6653                                 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);
6654                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6655                         }
6656
6657                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6658                         {
6659                                 // declare variables
6660                                 float blur_factor, blur_mouseaccel, blur_velocity;
6661                                 static float blur_average; 
6662                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6663
6664                                 // set a goal for the factoring
6665                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6666                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6667                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6668                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6669                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6670                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6671
6672                                 // from the goal, pick an averaged value between goal and last value
6673                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6674                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6675
6676                                 // enforce minimum amount of blur 
6677                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6678
6679                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6680
6681                                 // calculate values into a standard alpha
6682                                 cl.motionbluralpha = 1 - exp(-
6683                                                 (
6684                                                  (r_motionblur.value * blur_factor / 80)
6685                                                  +
6686                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6687                                                 )
6688                                                 /
6689                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6690                                           );
6691
6692                                 // randomization for the blur value to combat persistent ghosting
6693                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6694                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6695
6696                                 // apply the blur
6697                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6698                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6699                                 {
6700                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6701                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6702                                         switch(vid.renderpath)
6703                                         {
6704                                         case RENDERPATH_GL11:
6705                                         case RENDERPATH_GL13:
6706                                         case RENDERPATH_GL20:
6707                                         case RENDERPATH_GLES1:
6708                                         case RENDERPATH_GLES2:
6709                                         case RENDERPATH_SOFT:
6710                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6711                                                 break;
6712                                         case RENDERPATH_D3D9:
6713                                         case RENDERPATH_D3D10:
6714                                         case RENDERPATH_D3D11:
6715                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6716                                                 break;
6717                                         }
6718                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6719                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6720                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6721                                 }
6722
6723                                 // updates old view angles for next pass
6724                                 VectorCopy(cl.viewangles, blur_oldangles);
6725
6726                                 // copy view into the ghost texture
6727                                 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);
6728                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6729                                 r_fb.ghosttexture_valid = true;
6730                         }
6731                 }
6732                 else
6733                 {
6734                         // no r_fb.colortexture means we're rendering to the real fb
6735                         // we may still have to do view tint...
6736                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6737                         {
6738                                 // apply a color tint to the whole view
6739                                 R_ResetViewRendering2D(0, NULL, NULL);
6740                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6741                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6742                                 R_SetupShader_Generic_NoTexture(false, true);
6743                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6744                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6745                         }
6746                         break; // no screen processing, no bloom, skip it
6747                 }
6748
6749                 if (r_fb.bloomtexture[0])
6750                 {
6751                         // make the bloom texture
6752                         R_Bloom_MakeTexture();
6753                 }
6754
6755 #if _MSC_VER >= 1400
6756 #define sscanf sscanf_s
6757 #endif
6758                 memset(uservecs, 0, sizeof(uservecs));
6759                 if (r_glsl_postprocess_uservec1_enable.integer)
6760                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6761                 if (r_glsl_postprocess_uservec2_enable.integer)
6762                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6763                 if (r_glsl_postprocess_uservec3_enable.integer)
6764                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6765                 if (r_glsl_postprocess_uservec4_enable.integer)
6766                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6767
6768                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6769                 GL_Color(1, 1, 1, 1);
6770                 GL_BlendFunc(GL_ONE, GL_ZERO);
6771
6772                 switch(vid.renderpath)
6773                 {
6774                 case RENDERPATH_GL20:
6775                 case RENDERPATH_GLES2:
6776                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6777                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6778                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6779                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6780                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6781                         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]);
6782                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6783                         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]);
6784                         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]);
6785                         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]);
6786                         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]);
6787                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6788                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6789                         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);
6790                         break;
6791                 case RENDERPATH_D3D9:
6792 #ifdef SUPPORTD3D
6793                         // 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...
6794                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6795                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6796                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6797                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6798                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6799                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6800                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6801                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6802                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6803                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6804                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6805                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6806                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6807                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6808 #endif
6809                         break;
6810                 case RENDERPATH_D3D10:
6811                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6812                         break;
6813                 case RENDERPATH_D3D11:
6814                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6815                         break;
6816                 case RENDERPATH_SOFT:
6817                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6818                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6819                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6820                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6821                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6822                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6823                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6824                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6825                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6826                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6827                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6828                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6829                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6830                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6831                         break;
6832                 default:
6833                         break;
6834                 }
6835                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6836                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6837                 break;
6838         case RENDERPATH_GL11:
6839         case RENDERPATH_GL13:
6840         case RENDERPATH_GLES1:
6841                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6842                 {
6843                         // apply a color tint to the whole view
6844                         R_ResetViewRendering2D(0, NULL, NULL);
6845                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6846                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6847                         R_SetupShader_Generic_NoTexture(false, true);
6848                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6849                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6850                 }
6851                 break;
6852         }
6853 }
6854
6855 matrix4x4_t r_waterscrollmatrix;
6856
6857 void R_UpdateFog(void)
6858 {
6859         // Nehahra fog
6860         if (gamemode == GAME_NEHAHRA)
6861         {
6862                 if (gl_fogenable.integer)
6863                 {
6864                         r_refdef.oldgl_fogenable = true;
6865                         r_refdef.fog_density = gl_fogdensity.value;
6866                         r_refdef.fog_red = gl_fogred.value;
6867                         r_refdef.fog_green = gl_foggreen.value;
6868                         r_refdef.fog_blue = gl_fogblue.value;
6869                         r_refdef.fog_alpha = 1;
6870                         r_refdef.fog_start = 0;
6871                         r_refdef.fog_end = gl_skyclip.value;
6872                         r_refdef.fog_height = 1<<30;
6873                         r_refdef.fog_fadedepth = 128;
6874                 }
6875                 else if (r_refdef.oldgl_fogenable)
6876                 {
6877                         r_refdef.oldgl_fogenable = false;
6878                         r_refdef.fog_density = 0;
6879                         r_refdef.fog_red = 0;
6880                         r_refdef.fog_green = 0;
6881                         r_refdef.fog_blue = 0;
6882                         r_refdef.fog_alpha = 0;
6883                         r_refdef.fog_start = 0;
6884                         r_refdef.fog_end = 0;
6885                         r_refdef.fog_height = 1<<30;
6886                         r_refdef.fog_fadedepth = 128;
6887                 }
6888         }
6889
6890         // fog parms
6891         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6892         r_refdef.fog_start = max(0, r_refdef.fog_start);
6893         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6894
6895         if (r_refdef.fog_density && r_drawfog.integer)
6896         {
6897                 r_refdef.fogenabled = true;
6898                 // this is the point where the fog reaches 0.9986 alpha, which we
6899                 // consider a good enough cutoff point for the texture
6900                 // (0.9986 * 256 == 255.6)
6901                 if (r_fog_exp2.integer)
6902                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6903                 else
6904                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6905                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6906                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6907                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6908                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6909                         R_BuildFogHeightTexture();
6910                 // fog color was already set
6911                 // update the fog texture
6912                 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)
6913                         R_BuildFogTexture();
6914                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6915                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6916         }
6917         else
6918                 r_refdef.fogenabled = false;
6919
6920         // fog color
6921         if (r_refdef.fog_density)
6922         {
6923                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6924                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6925                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6926
6927                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6928                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6929                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6930                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6931
6932                 {
6933                         vec3_t fogvec;
6934                         VectorCopy(r_refdef.fogcolor, fogvec);
6935                         //   color.rgb *= ContrastBoost * SceneBrightness;
6936                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6937                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6938                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6939                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6940                 }
6941         }
6942 }
6943
6944 void R_UpdateVariables(void)
6945 {
6946         R_Textures_Frame();
6947
6948         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6949
6950         r_refdef.farclip = r_farclip_base.value;
6951         if (r_refdef.scene.worldmodel)
6952                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6953         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6954
6955         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6956                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6957         r_refdef.polygonfactor = 0;
6958         r_refdef.polygonoffset = 0;
6959         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6960         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6961
6962         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6963         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6964         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6965         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6966         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6967         if (FAKELIGHT_ENABLED)
6968         {
6969                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6970         }
6971         else if (r_refdef.scene.worldmodel)
6972         {
6973                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6974         }
6975         if (r_showsurfaces.integer)
6976         {
6977                 r_refdef.scene.rtworld = false;
6978                 r_refdef.scene.rtworldshadows = false;
6979                 r_refdef.scene.rtdlight = false;
6980                 r_refdef.scene.rtdlightshadows = false;
6981                 r_refdef.lightmapintensity = 0;
6982         }
6983
6984         r_gpuskeletal = false;
6985         switch(vid.renderpath)
6986         {
6987         case RENDERPATH_GL20:
6988                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6989         case RENDERPATH_D3D9:
6990         case RENDERPATH_D3D10:
6991         case RENDERPATH_D3D11:
6992         case RENDERPATH_SOFT:
6993         case RENDERPATH_GLES2:
6994                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6995                 {
6996                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6997                         {
6998                                 // build GLSL gamma texture
6999 #define RAMPWIDTH 256
7000                                 unsigned short ramp[RAMPWIDTH * 3];
7001                                 unsigned char rampbgr[RAMPWIDTH][4];
7002                                 int i;
7003
7004                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7005
7006                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7007                                 for(i = 0; i < RAMPWIDTH; ++i)
7008                                 {
7009                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7010                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7011                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7012                                         rampbgr[i][3] = 0;
7013                                 }
7014                                 if (r_texture_gammaramps)
7015                                 {
7016                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7017                                 }
7018                                 else
7019                                 {
7020                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7021                                 }
7022                         }
7023                 }
7024                 else
7025                 {
7026                         // remove GLSL gamma texture
7027                 }
7028                 break;
7029         case RENDERPATH_GL11:
7030         case RENDERPATH_GL13:
7031         case RENDERPATH_GLES1:
7032                 break;
7033         }
7034 }
7035
7036 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7037 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7038 /*
7039 ================
7040 R_SelectScene
7041 ================
7042 */
7043 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7044         if( scenetype != r_currentscenetype ) {
7045                 // store the old scenetype
7046                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7047                 r_currentscenetype = scenetype;
7048                 // move in the new scene
7049                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7050         }
7051 }
7052
7053 /*
7054 ================
7055 R_GetScenePointer
7056 ================
7057 */
7058 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7059 {
7060         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7061         if( scenetype == r_currentscenetype ) {
7062                 return &r_refdef.scene;
7063         } else {
7064                 return &r_scenes_store[ scenetype ];
7065         }
7066 }
7067
7068 static int R_SortEntities_Compare(const void *ap, const void *bp)
7069 {
7070         const entity_render_t *a = *(const entity_render_t **)ap;
7071         const entity_render_t *b = *(const entity_render_t **)bp;
7072
7073         // 1. compare model
7074         if(a->model < b->model)
7075                 return -1;
7076         if(a->model > b->model)
7077                 return +1;
7078
7079         // 2. compare skin
7080         // TODO possibly calculate the REAL skinnum here first using
7081         // skinscenes?
7082         if(a->skinnum < b->skinnum)
7083                 return -1;
7084         if(a->skinnum > b->skinnum)
7085                 return +1;
7086
7087         // everything we compared is equal
7088         return 0;
7089 }
7090 static void R_SortEntities(void)
7091 {
7092         // below or equal 2 ents, sorting never gains anything
7093         if(r_refdef.scene.numentities <= 2)
7094                 return;
7095         // sort
7096         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7097 }
7098
7099 /*
7100 ================
7101 R_RenderView
7102 ================
7103 */
7104 int dpsoftrast_test;
7105 extern cvar_t r_shadow_bouncegrid;
7106 void R_RenderView(void)
7107 {
7108         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7109         int fbo;
7110         rtexture_t *depthtexture;
7111         rtexture_t *colortexture;
7112
7113         dpsoftrast_test = r_test.integer;
7114
7115         if (r_timereport_active)
7116                 R_TimeReport("start");
7117         r_textureframe++; // used only by R_GetCurrentTexture
7118         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7119
7120         if(R_CompileShader_CheckStaticParms())
7121                 R_GLSL_Restart_f();
7122
7123         if (!r_drawentities.integer)
7124                 r_refdef.scene.numentities = 0;
7125         else if (r_sortentities.integer)
7126                 R_SortEntities();
7127
7128         R_AnimCache_ClearCache();
7129         R_FrameData_NewFrame();
7130         R_BufferData_NewFrame();
7131
7132         /* adjust for stereo display */
7133         if(R_Stereo_Active())
7134         {
7135                 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);
7136                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7137         }
7138
7139         if (r_refdef.view.isoverlay)
7140         {
7141                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7142                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7143                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7144                 R_TimeReport("depthclear");
7145
7146                 r_refdef.view.showdebug = false;
7147
7148                 r_fb.water.enabled = false;
7149                 r_fb.water.numwaterplanes = 0;
7150
7151                 R_RenderScene(0, NULL, NULL);
7152
7153                 r_refdef.view.matrix = originalmatrix;
7154
7155                 CHECKGLERROR
7156                 return;
7157         }
7158
7159         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7160         {
7161                 r_refdef.view.matrix = originalmatrix;
7162                 return;
7163         }
7164
7165         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7166
7167         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7168                 // in sRGB fallback, behave similar to true sRGB: convert this
7169                 // value from linear to sRGB
7170                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7171
7172         R_RenderView_UpdateViewVectors();
7173
7174         R_Shadow_UpdateWorldLightSelection();
7175
7176         R_Bloom_StartFrame();
7177
7178         // apply bloom brightness offset
7179         if(r_fb.bloomtexture[0])
7180                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7181
7182         R_Water_StartFrame();
7183
7184         // now we probably have an fbo to render into
7185         fbo = r_fb.fbo;
7186         depthtexture = r_fb.depthtexture;
7187         colortexture = r_fb.colortexture;
7188
7189         CHECKGLERROR
7190         if (r_timereport_active)
7191                 R_TimeReport("viewsetup");
7192
7193         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7194
7195         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7196         {
7197                 R_ClearScreen(r_refdef.fogenabled);
7198                 if (r_timereport_active)
7199                         R_TimeReport("viewclear");
7200         }
7201         r_refdef.view.clear = true;
7202
7203         r_refdef.view.showdebug = true;
7204
7205         R_View_Update();
7206         if (r_timereport_active)
7207                 R_TimeReport("visibility");
7208
7209         R_AnimCache_CacheVisibleEntities();
7210         if (r_timereport_active)
7211                 R_TimeReport("animcache");
7212
7213         R_Shadow_UpdateBounceGridTexture();
7214         if (r_timereport_active && r_shadow_bouncegrid.integer)
7215                 R_TimeReport("bouncegrid");
7216
7217         r_fb.water.numwaterplanes = 0;
7218         if (r_fb.water.enabled)
7219                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7220
7221         R_RenderScene(fbo, depthtexture, colortexture);
7222         r_fb.water.numwaterplanes = 0;
7223
7224         R_BlendView(fbo, depthtexture, colortexture);
7225         if (r_timereport_active)
7226                 R_TimeReport("blendview");
7227
7228         GL_Scissor(0, 0, vid.width, vid.height);
7229         GL_ScissorTest(false);
7230
7231         r_refdef.view.matrix = originalmatrix;
7232
7233         CHECKGLERROR
7234 }
7235
7236 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7237 {
7238         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7239         {
7240                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7241                 if (r_timereport_active)
7242                         R_TimeReport("waterworld");
7243         }
7244
7245         // don't let sound skip if going slow
7246         if (r_refdef.scene.extraupdate)
7247                 S_ExtraUpdate ();
7248
7249         R_DrawModelsAddWaterPlanes();
7250         if (r_timereport_active)
7251                 R_TimeReport("watermodels");
7252
7253         if (r_fb.water.numwaterplanes)
7254         {
7255                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7256                 if (r_timereport_active)
7257                         R_TimeReport("waterscenes");
7258         }
7259 }
7260
7261 extern cvar_t cl_locs_show;
7262 static void R_DrawLocs(void);
7263 static void R_DrawEntityBBoxes(void);
7264 static void R_DrawModelDecals(void);
7265 extern cvar_t cl_decals_newsystem;
7266 extern qboolean r_shadow_usingdeferredprepass;
7267 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7268 {
7269         qboolean shadowmapping = false;
7270
7271         if (r_timereport_active)
7272                 R_TimeReport("beginscene");
7273
7274         r_refdef.stats[r_stat_renders]++;
7275
7276         R_UpdateFog();
7277
7278         // don't let sound skip if going slow
7279         if (r_refdef.scene.extraupdate)
7280                 S_ExtraUpdate ();
7281
7282         R_MeshQueue_BeginScene();
7283
7284         R_SkyStartFrame();
7285
7286         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);
7287
7288         if (r_timereport_active)
7289                 R_TimeReport("skystartframe");
7290
7291         if (cl.csqc_vidvars.drawworld)
7292         {
7293                 // don't let sound skip if going slow
7294                 if (r_refdef.scene.extraupdate)
7295                         S_ExtraUpdate ();
7296
7297                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7298                 {
7299                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7300                         if (r_timereport_active)
7301                                 R_TimeReport("worldsky");
7302                 }
7303
7304                 if (R_DrawBrushModelsSky() && r_timereport_active)
7305                         R_TimeReport("bmodelsky");
7306
7307                 if (skyrendermasked && skyrenderlater)
7308                 {
7309                         // we have to force off the water clipping plane while rendering sky
7310                         R_SetupView(false, fbo, depthtexture, colortexture);
7311                         R_Sky();
7312                         R_SetupView(true, fbo, depthtexture, colortexture);
7313                         if (r_timereport_active)
7314                                 R_TimeReport("sky");
7315                 }
7316         }
7317
7318         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7319         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7320                 R_Shadow_PrepareModelShadows();
7321         if (r_timereport_active)
7322                 R_TimeReport("preparelights");
7323
7324         if (R_Shadow_ShadowMappingEnabled())
7325                 shadowmapping = true;
7326
7327         if (r_shadow_usingdeferredprepass)
7328                 R_Shadow_DrawPrepass();
7329
7330         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7331         {
7332                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7333                 if (r_timereport_active)
7334                         R_TimeReport("worlddepth");
7335         }
7336         if (r_depthfirst.integer >= 2)
7337         {
7338                 R_DrawModelsDepth();
7339                 if (r_timereport_active)
7340                         R_TimeReport("modeldepth");
7341         }
7342
7343         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7344         {
7345                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7346                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7347                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7348                 // don't let sound skip if going slow
7349                 if (r_refdef.scene.extraupdate)
7350                         S_ExtraUpdate ();
7351         }
7352
7353         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7354         {
7355                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7356                 if (r_timereport_active)
7357                         R_TimeReport("world");
7358         }
7359
7360         // don't let sound skip if going slow
7361         if (r_refdef.scene.extraupdate)
7362                 S_ExtraUpdate ();
7363
7364         R_DrawModels();
7365         if (r_timereport_active)
7366                 R_TimeReport("models");
7367
7368         // don't let sound skip if going slow
7369         if (r_refdef.scene.extraupdate)
7370                 S_ExtraUpdate ();
7371
7372         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7373         {
7374                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7375                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7376                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7377                 // don't let sound skip if going slow
7378                 if (r_refdef.scene.extraupdate)
7379                         S_ExtraUpdate ();
7380         }
7381
7382         if (!r_shadow_usingdeferredprepass)
7383         {
7384                 R_Shadow_DrawLights();
7385                 if (r_timereport_active)
7386                         R_TimeReport("rtlights");
7387         }
7388
7389         // don't let sound skip if going slow
7390         if (r_refdef.scene.extraupdate)
7391                 S_ExtraUpdate ();
7392
7393         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7394         {
7395                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7396                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7397                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7398                 // don't let sound skip if going slow
7399                 if (r_refdef.scene.extraupdate)
7400                         S_ExtraUpdate ();
7401         }
7402
7403         if (cl.csqc_vidvars.drawworld)
7404         {
7405                 if (cl_decals_newsystem.integer)
7406                 {
7407                         R_DrawModelDecals();
7408                         if (r_timereport_active)
7409                                 R_TimeReport("modeldecals");
7410                 }
7411                 else
7412                 {
7413                         R_DrawDecals();
7414                         if (r_timereport_active)
7415                                 R_TimeReport("decals");
7416                 }
7417
7418                 R_DrawParticles();
7419                 if (r_timereport_active)
7420                         R_TimeReport("particles");
7421
7422                 R_DrawExplosions();
7423                 if (r_timereport_active)
7424                         R_TimeReport("explosions");
7425
7426                 R_DrawLightningBeams();
7427                 if (r_timereport_active)
7428                         R_TimeReport("lightning");
7429         }
7430
7431         if (cl.csqc_loaded)
7432                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7433
7434         if (r_refdef.view.showdebug)
7435         {
7436                 if (cl_locs_show.integer)
7437                 {
7438                         R_DrawLocs();
7439                         if (r_timereport_active)
7440                                 R_TimeReport("showlocs");
7441                 }
7442
7443                 if (r_drawportals.integer)
7444                 {
7445                         R_DrawPortals();
7446                         if (r_timereport_active)
7447                                 R_TimeReport("portals");
7448                 }
7449
7450                 if (r_showbboxes.value > 0)
7451                 {
7452                         R_DrawEntityBBoxes();
7453                         if (r_timereport_active)
7454                                 R_TimeReport("bboxes");
7455                 }
7456         }
7457
7458         if (r_transparent.integer)
7459         {
7460                 R_MeshQueue_RenderTransparent();
7461                 if (r_timereport_active)
7462                         R_TimeReport("drawtrans");
7463         }
7464
7465         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))
7466         {
7467                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7468                 if (r_timereport_active)
7469                         R_TimeReport("worlddebug");
7470                 R_DrawModelsDebug();
7471                 if (r_timereport_active)
7472                         R_TimeReport("modeldebug");
7473         }
7474
7475         if (cl.csqc_vidvars.drawworld)
7476         {
7477                 R_Shadow_DrawCoronas();
7478                 if (r_timereport_active)
7479                         R_TimeReport("coronas");
7480         }
7481
7482 #if 0
7483         {
7484                 GL_DepthTest(false);
7485                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7486                 GL_Color(1, 1, 1, 1);
7487                 qglBegin(GL_POLYGON);
7488                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7489                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7490                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7491                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7492                 qglEnd();
7493                 qglBegin(GL_POLYGON);
7494                 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]);
7495                 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]);
7496                 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]);
7497                 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]);
7498                 qglEnd();
7499                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7500         }
7501 #endif
7502
7503         // don't let sound skip if going slow
7504         if (r_refdef.scene.extraupdate)
7505                 S_ExtraUpdate ();
7506 }
7507
7508 static const unsigned short bboxelements[36] =
7509 {
7510         5, 1, 3, 5, 3, 7,
7511         6, 2, 0, 6, 0, 4,
7512         7, 3, 2, 7, 2, 6,
7513         4, 0, 1, 4, 1, 5,
7514         4, 5, 7, 4, 7, 6,
7515         1, 0, 2, 1, 2, 3,
7516 };
7517
7518 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7519 {
7520         int i;
7521         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7522
7523         RSurf_ActiveWorldEntity();
7524
7525         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7526         GL_DepthMask(false);
7527         GL_DepthRange(0, 1);
7528         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7529 //      R_Mesh_ResetTextureState();
7530
7531         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7532         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7533         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7534         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7535         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7536         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7537         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7538         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7539         R_FillColors(color4f, 8, cr, cg, cb, ca);
7540         if (r_refdef.fogenabled)
7541         {
7542                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7543                 {
7544                         f1 = RSurf_FogVertex(v);
7545                         f2 = 1 - f1;
7546                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7547                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7548                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7549                 }
7550         }
7551         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7552         R_Mesh_ResetTextureState();
7553         R_SetupShader_Generic_NoTexture(false, false);
7554         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7555 }
7556
7557 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7558 {
7559         prvm_prog_t *prog = SVVM_prog;
7560         int i;
7561         float color[4];
7562         prvm_edict_t *edict;
7563
7564         // this function draws bounding boxes of server entities
7565         if (!sv.active)
7566                 return;
7567
7568         GL_CullFace(GL_NONE);
7569         R_SetupShader_Generic_NoTexture(false, false);
7570
7571         for (i = 0;i < numsurfaces;i++)
7572         {
7573                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7574                 switch ((int)PRVM_serveredictfloat(edict, solid))
7575                 {
7576                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7577                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7578                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7579                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7580                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7581                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7582                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7583                 }
7584                 color[3] *= r_showbboxes.value;
7585                 color[3] = bound(0, color[3], 1);
7586                 GL_DepthTest(!r_showdisabledepthtest.integer);
7587                 GL_CullFace(r_refdef.view.cullface_front);
7588                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7589         }
7590 }
7591
7592 static void R_DrawEntityBBoxes(void)
7593 {
7594         int i;
7595         prvm_edict_t *edict;
7596         vec3_t center;
7597         prvm_prog_t *prog = SVVM_prog;
7598
7599         // this function draws bounding boxes of server entities
7600         if (!sv.active)
7601                 return;
7602
7603         for (i = 0;i < prog->num_edicts;i++)
7604         {
7605                 edict = PRVM_EDICT_NUM(i);
7606                 if (edict->priv.server->free)
7607                         continue;
7608                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7609                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7610                         continue;
7611                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7612                         continue;
7613                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7614                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7615         }
7616 }
7617
7618 static const int nomodelelement3i[24] =
7619 {
7620         5, 2, 0,
7621         5, 1, 2,
7622         5, 0, 3,
7623         5, 3, 1,
7624         0, 2, 4,
7625         2, 1, 4,
7626         3, 0, 4,
7627         1, 3, 4
7628 };
7629
7630 static const unsigned short nomodelelement3s[24] =
7631 {
7632         5, 2, 0,
7633         5, 1, 2,
7634         5, 0, 3,
7635         5, 3, 1,
7636         0, 2, 4,
7637         2, 1, 4,
7638         3, 0, 4,
7639         1, 3, 4
7640 };
7641
7642 static const float nomodelvertex3f[6*3] =
7643 {
7644         -16,   0,   0,
7645          16,   0,   0,
7646           0, -16,   0,
7647           0,  16,   0,
7648           0,   0, -16,
7649           0,   0,  16
7650 };
7651
7652 static const float nomodelcolor4f[6*4] =
7653 {
7654         0.0f, 0.0f, 0.5f, 1.0f,
7655         0.0f, 0.0f, 0.5f, 1.0f,
7656         0.0f, 0.5f, 0.0f, 1.0f,
7657         0.0f, 0.5f, 0.0f, 1.0f,
7658         0.5f, 0.0f, 0.0f, 1.0f,
7659         0.5f, 0.0f, 0.0f, 1.0f
7660 };
7661
7662 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7663 {
7664         int i;
7665         float f1, f2, *c;
7666         float color4f[6*4];
7667
7668         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);
7669
7670         // this is only called once per entity so numsurfaces is always 1, and
7671         // surfacelist is always {0}, so this code does not handle batches
7672
7673         if (rsurface.ent_flags & RENDER_ADDITIVE)
7674         {
7675                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7676                 GL_DepthMask(false);
7677         }
7678         else if (rsurface.colormod[3] < 1)
7679         {
7680                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7681                 GL_DepthMask(false);
7682         }
7683         else
7684         {
7685                 GL_BlendFunc(GL_ONE, GL_ZERO);
7686                 GL_DepthMask(true);
7687         }
7688         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7689         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7690         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7691         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7692         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7693         for (i = 0, c = color4f;i < 6;i++, c += 4)
7694         {
7695                 c[0] *= rsurface.colormod[0];
7696                 c[1] *= rsurface.colormod[1];
7697                 c[2] *= rsurface.colormod[2];
7698                 c[3] *= rsurface.colormod[3];
7699         }
7700         if (r_refdef.fogenabled)
7701         {
7702                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7703                 {
7704                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7705                         f2 = 1 - f1;
7706                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7707                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7708                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7709                 }
7710         }
7711 //      R_Mesh_ResetTextureState();
7712         R_SetupShader_Generic_NoTexture(false, false);
7713         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7714         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7715 }
7716
7717 void R_DrawNoModel(entity_render_t *ent)
7718 {
7719         vec3_t org;
7720         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7721         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7722                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7723         else
7724                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7725 }
7726
7727 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7728 {
7729         vec3_t right1, right2, diff, normal;
7730
7731         VectorSubtract (org2, org1, normal);
7732
7733         // calculate 'right' vector for start
7734         VectorSubtract (r_refdef.view.origin, org1, diff);
7735         CrossProduct (normal, diff, right1);
7736         VectorNormalize (right1);
7737
7738         // calculate 'right' vector for end
7739         VectorSubtract (r_refdef.view.origin, org2, diff);
7740         CrossProduct (normal, diff, right2);
7741         VectorNormalize (right2);
7742
7743         vert[ 0] = org1[0] + width * right1[0];
7744         vert[ 1] = org1[1] + width * right1[1];
7745         vert[ 2] = org1[2] + width * right1[2];
7746         vert[ 3] = org1[0] - width * right1[0];
7747         vert[ 4] = org1[1] - width * right1[1];
7748         vert[ 5] = org1[2] - width * right1[2];
7749         vert[ 6] = org2[0] - width * right2[0];
7750         vert[ 7] = org2[1] - width * right2[1];
7751         vert[ 8] = org2[2] - width * right2[2];
7752         vert[ 9] = org2[0] + width * right2[0];
7753         vert[10] = org2[1] + width * right2[1];
7754         vert[11] = org2[2] + width * right2[2];
7755 }
7756
7757 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)
7758 {
7759         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7760         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7761         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7762         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7763         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7764         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7765         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7766         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7767         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7768         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7769         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7770         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7771 }
7772
7773 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7774 {
7775         int i;
7776         float *vertex3f;
7777         float v[3];
7778         VectorSet(v, x, y, z);
7779         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7780                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7781                         break;
7782         if (i == mesh->numvertices)
7783         {
7784                 if (mesh->numvertices < mesh->maxvertices)
7785                 {
7786                         VectorCopy(v, vertex3f);
7787                         mesh->numvertices++;
7788                 }
7789                 return mesh->numvertices;
7790         }
7791         else
7792                 return i;
7793 }
7794
7795 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7796 {
7797         int i;
7798         int *e, element[3];
7799         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7800         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7801         e = mesh->element3i + mesh->numtriangles * 3;
7802         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7803         {
7804                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7805                 if (mesh->numtriangles < mesh->maxtriangles)
7806                 {
7807                         *e++ = element[0];
7808                         *e++ = element[1];
7809                         *e++ = element[2];
7810                         mesh->numtriangles++;
7811                 }
7812                 element[1] = element[2];
7813         }
7814 }
7815
7816 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7817 {
7818         int i;
7819         int *e, element[3];
7820         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7821         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7822         e = mesh->element3i + mesh->numtriangles * 3;
7823         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7824         {
7825                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7826                 if (mesh->numtriangles < mesh->maxtriangles)
7827                 {
7828                         *e++ = element[0];
7829                         *e++ = element[1];
7830                         *e++ = element[2];
7831                         mesh->numtriangles++;
7832                 }
7833                 element[1] = element[2];
7834         }
7835 }
7836
7837 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7838 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7839 {
7840         int planenum, planenum2;
7841         int w;
7842         int tempnumpoints;
7843         mplane_t *plane, *plane2;
7844         double maxdist;
7845         double temppoints[2][256*3];
7846         // figure out how large a bounding box we need to properly compute this brush
7847         maxdist = 0;
7848         for (w = 0;w < numplanes;w++)
7849                 maxdist = max(maxdist, fabs(planes[w].dist));
7850         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7851         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7852         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7853         {
7854                 w = 0;
7855                 tempnumpoints = 4;
7856                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7857                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7858                 {
7859                         if (planenum2 == planenum)
7860                                 continue;
7861                         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);
7862                         w = !w;
7863                 }
7864                 if (tempnumpoints < 3)
7865                         continue;
7866                 // generate elements forming a triangle fan for this polygon
7867                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7868         }
7869 }
7870
7871 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)
7872 {
7873         texturelayer_t *layer;
7874         layer = t->currentlayers + t->currentnumlayers++;
7875         layer->type = type;
7876         layer->depthmask = depthmask;
7877         layer->blendfunc1 = blendfunc1;
7878         layer->blendfunc2 = blendfunc2;
7879         layer->texture = texture;
7880         layer->texmatrix = *matrix;
7881         layer->color[0] = r;
7882         layer->color[1] = g;
7883         layer->color[2] = b;
7884         layer->color[3] = a;
7885 }
7886
7887 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7888 {
7889         if(parms[0] == 0 && parms[1] == 0)
7890                 return false;
7891         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7892                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7893                         return false;
7894         return true;
7895 }
7896
7897 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7898 {
7899         double index, f;
7900         index = parms[2] + rsurface.shadertime * parms[3];
7901         index -= floor(index);
7902         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7903         {
7904         default:
7905         case Q3WAVEFUNC_NONE:
7906         case Q3WAVEFUNC_NOISE:
7907         case Q3WAVEFUNC_COUNT:
7908                 f = 0;
7909                 break;
7910         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7911         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7912         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7913         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7914         case Q3WAVEFUNC_TRIANGLE:
7915                 index *= 4;
7916                 f = index - floor(index);
7917                 if (index < 1)
7918                 {
7919                         // f = f;
7920                 }
7921                 else if (index < 2)
7922                         f = 1 - f;
7923                 else if (index < 3)
7924                         f = -f;
7925                 else
7926                         f = -(1 - f);
7927                 break;
7928         }
7929         f = parms[0] + parms[1] * f;
7930         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7931                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7932         return (float) f;
7933 }
7934
7935 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7936 {
7937         int w, h, idx;
7938         double f;
7939         double offsetd[2];
7940         float tcmat[12];
7941         matrix4x4_t matrix, temp;
7942         switch(tcmod->tcmod)
7943         {
7944                 case Q3TCMOD_COUNT:
7945                 case Q3TCMOD_NONE:
7946                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7947                                 matrix = r_waterscrollmatrix;
7948                         else
7949                                 matrix = identitymatrix;
7950                         break;
7951                 case Q3TCMOD_ENTITYTRANSLATE:
7952                         // this is used in Q3 to allow the gamecode to control texcoord
7953                         // scrolling on the entity, which is not supported in darkplaces yet.
7954                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7955                         break;
7956                 case Q3TCMOD_ROTATE:
7957                         f = tcmod->parms[0] * rsurface.shadertime;
7958                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7959                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7960                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7961                         break;
7962                 case Q3TCMOD_SCALE:
7963                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7964                         break;
7965                 case Q3TCMOD_SCROLL:
7966                         // extra care is needed because of precision breakdown with large values of time
7967                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7968                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7969                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7970                         break;
7971                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7972                         w = (int) tcmod->parms[0];
7973                         h = (int) tcmod->parms[1];
7974                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7975                         f = f - floor(f);
7976                         idx = (int) floor(f * w * h);
7977                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7978                         break;
7979                 case Q3TCMOD_STRETCH:
7980                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7981                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7982                         break;
7983                 case Q3TCMOD_TRANSFORM:
7984                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7985                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7986                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7987                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7988                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7989                         break;
7990                 case Q3TCMOD_TURBULENT:
7991                         // this is handled in the RSurf_PrepareVertices function
7992                         matrix = identitymatrix;
7993                         break;
7994         }
7995         temp = *texmatrix;
7996         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7997 }
7998
7999 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8000 {
8001         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8002         char name[MAX_QPATH];
8003         skinframe_t *skinframe;
8004         unsigned char pixels[296*194];
8005         strlcpy(cache->name, skinname, sizeof(cache->name));
8006         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8007         if (developer_loading.integer)
8008                 Con_Printf("loading %s\n", name);
8009         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8010         if (!skinframe || !skinframe->base)
8011         {
8012                 unsigned char *f;
8013                 fs_offset_t filesize;
8014                 skinframe = NULL;
8015                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8016                 if (f)
8017                 {
8018                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8019                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8020                         Mem_Free(f);
8021                 }
8022         }
8023         cache->skinframe = skinframe;
8024 }
8025
8026 texture_t *R_GetCurrentTexture(texture_t *t)
8027 {
8028         int i;
8029         const entity_render_t *ent = rsurface.entity;
8030         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8031         q3shaderinfo_layer_tcmod_t *tcmod;
8032
8033         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8034                 return t->currentframe;
8035         t->update_lastrenderframe = r_textureframe;
8036         t->update_lastrenderentity = (void *)ent;
8037
8038         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8039                 t->camera_entity = ent->entitynumber;
8040         else
8041                 t->camera_entity = 0;
8042
8043         // switch to an alternate material if this is a q1bsp animated material
8044         {
8045                 texture_t *texture = t;
8046                 int s = rsurface.ent_skinnum;
8047                 if ((unsigned int)s >= (unsigned int)model->numskins)
8048                         s = 0;
8049                 if (model->skinscenes)
8050                 {
8051                         if (model->skinscenes[s].framecount > 1)
8052                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8053                         else
8054                                 s = model->skinscenes[s].firstframe;
8055                 }
8056                 if (s > 0)
8057                         t = t + s * model->num_surfaces;
8058                 if (t->animated)
8059                 {
8060                         // use an alternate animation if the entity's frame is not 0,
8061                         // and only if the texture has an alternate animation
8062                         if (rsurface.ent_alttextures && t->anim_total[1])
8063                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8064                         else
8065                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8066                 }
8067                 texture->currentframe = t;
8068         }
8069
8070         // update currentskinframe to be a qw skin or animation frame
8071         if (rsurface.ent_qwskin >= 0)
8072         {
8073                 i = rsurface.ent_qwskin;
8074                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8075                 {
8076                         r_qwskincache_size = cl.maxclients;
8077                         if (r_qwskincache)
8078                                 Mem_Free(r_qwskincache);
8079                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8080                 }
8081                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8082                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8083                 t->currentskinframe = r_qwskincache[i].skinframe;
8084                 if (t->currentskinframe == NULL)
8085                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8086         }
8087         else if (t->numskinframes >= 2)
8088                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8089         if (t->backgroundnumskinframes >= 2)
8090                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8091
8092         t->currentmaterialflags = t->basematerialflags;
8093         t->currentalpha = rsurface.colormod[3];
8094         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8095                 t->currentalpha *= r_wateralpha.value;
8096         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8097                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8098         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8099                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8100         if (!(rsurface.ent_flags & RENDER_LIGHT))
8101                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8102         else if (FAKELIGHT_ENABLED)
8103         {
8104                 // no modellight if using fakelight for the map
8105         }
8106         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8107         {
8108                 // pick a model lighting mode
8109                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8110                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8111                 else
8112                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8113         }
8114         if (rsurface.ent_flags & RENDER_ADDITIVE)
8115                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8116         else if (t->currentalpha < 1)
8117                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8118         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8119         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8120                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8121         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8122                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8123         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8124                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8125         if (t->backgroundnumskinframes)
8126                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8127         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8128         {
8129                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8130                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8131         }
8132         else
8133                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8134         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8135         {
8136                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8137                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8138         }
8139         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8140                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8141
8142         // there is no tcmod
8143         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8144         {
8145                 t->currenttexmatrix = r_waterscrollmatrix;
8146                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8147         }
8148         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8149         {
8150                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8151                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8152         }
8153
8154         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8155                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8156         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8157                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8158
8159         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8160         if (t->currentskinframe->qpixels)
8161                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8162         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8163         if (!t->basetexture)
8164                 t->basetexture = r_texture_notexture;
8165         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8166         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8167         t->nmaptexture = t->currentskinframe->nmap;
8168         if (!t->nmaptexture)
8169                 t->nmaptexture = r_texture_blanknormalmap;
8170         t->glosstexture = r_texture_black;
8171         t->glowtexture = t->currentskinframe->glow;
8172         t->fogtexture = t->currentskinframe->fog;
8173         t->reflectmasktexture = t->currentskinframe->reflect;
8174         if (t->backgroundnumskinframes)
8175         {
8176                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8177                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8178                 t->backgroundglosstexture = r_texture_black;
8179                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8180                 if (!t->backgroundnmaptexture)
8181                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8182                 // make sure that if glow is going to be used, both textures are not NULL
8183                 if (!t->backgroundglowtexture && t->glowtexture)
8184                         t->backgroundglowtexture = r_texture_black;
8185                 if (!t->glowtexture && t->backgroundglowtexture)
8186                         t->glowtexture = r_texture_black;
8187         }
8188         else
8189         {
8190                 t->backgroundbasetexture = r_texture_white;
8191                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8192                 t->backgroundglosstexture = r_texture_black;
8193                 t->backgroundglowtexture = NULL;
8194         }
8195         t->specularpower = r_shadow_glossexponent.value;
8196         // TODO: store reference values for these in the texture?
8197         t->specularscale = 0;
8198         if (r_shadow_gloss.integer > 0)
8199         {
8200                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8201                 {
8202                         if (r_shadow_glossintensity.value > 0)
8203                         {
8204                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8205                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8206                                 t->specularscale = r_shadow_glossintensity.value;
8207                         }
8208                 }
8209                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8210                 {
8211                         t->glosstexture = r_texture_white;
8212                         t->backgroundglosstexture = r_texture_white;
8213                         t->specularscale = r_shadow_gloss2intensity.value;
8214                         t->specularpower = r_shadow_gloss2exponent.value;
8215                 }
8216         }
8217         t->specularscale *= t->specularscalemod;
8218         t->specularpower *= t->specularpowermod;
8219         t->rtlightambient = 0;
8220
8221         // lightmaps mode looks bad with dlights using actual texturing, so turn
8222         // off the colormap and glossmap, but leave the normalmap on as it still
8223         // accurately represents the shading involved
8224         if (gl_lightmaps.integer)
8225         {
8226                 t->basetexture = r_texture_grey128;
8227                 t->pantstexture = r_texture_black;
8228                 t->shirttexture = r_texture_black;
8229                 if (gl_lightmaps.integer < 2)
8230                         t->nmaptexture = r_texture_blanknormalmap;
8231                 t->glosstexture = r_texture_black;
8232                 t->glowtexture = NULL;
8233                 t->fogtexture = NULL;
8234                 t->reflectmasktexture = NULL;
8235                 t->backgroundbasetexture = NULL;
8236                 if (gl_lightmaps.integer < 2)
8237                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8238                 t->backgroundglosstexture = r_texture_black;
8239                 t->backgroundglowtexture = NULL;
8240                 t->specularscale = 0;
8241                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8242         }
8243
8244         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8245         VectorClear(t->dlightcolor);
8246         t->currentnumlayers = 0;
8247         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8248         {
8249                 int blendfunc1, blendfunc2;
8250                 qboolean depthmask;
8251                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8252                 {
8253                         blendfunc1 = GL_SRC_ALPHA;
8254                         blendfunc2 = GL_ONE;
8255                 }
8256                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8257                 {
8258                         blendfunc1 = GL_SRC_ALPHA;
8259                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8260                 }
8261                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8262                 {
8263                         blendfunc1 = t->customblendfunc[0];
8264                         blendfunc2 = t->customblendfunc[1];
8265                 }
8266                 else
8267                 {
8268                         blendfunc1 = GL_ONE;
8269                         blendfunc2 = GL_ZERO;
8270                 }
8271                 // don't colormod evilblend textures
8272                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8273                         VectorSet(t->lightmapcolor, 1, 1, 1);
8274                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8275                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8276                 {
8277                         // fullbright is not affected by r_refdef.lightmapintensity
8278                         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]);
8279                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8280                                 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]);
8281                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8282                                 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]);
8283                 }
8284                 else
8285                 {
8286                         vec3_t ambientcolor;
8287                         float colorscale;
8288                         // set the color tint used for lights affecting this surface
8289                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8290                         colorscale = 2;
8291                         // q3bsp has no lightmap updates, so the lightstylevalue that
8292                         // would normally be baked into the lightmap must be
8293                         // applied to the color
8294                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8295                         if (model->type == mod_brushq3)
8296                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8297                         colorscale *= r_refdef.lightmapintensity;
8298                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8299                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8300                         // basic lit geometry
8301                         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]);
8302                         // add pants/shirt if needed
8303                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8304                                 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]);
8305                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8306                                 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]);
8307                         // now add ambient passes if needed
8308                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8309                         {
8310                                 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]);
8311                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8312                                         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]);
8313                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8314                                         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]);
8315                         }
8316                 }
8317                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8318                         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]);
8319                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8320                 {
8321                         // if this is opaque use alpha blend which will darken the earlier
8322                         // passes cheaply.
8323                         //
8324                         // if this is an alpha blended material, all the earlier passes
8325                         // were darkened by fog already, so we only need to add the fog
8326                         // color ontop through the fog mask texture
8327                         //
8328                         // if this is an additive blended material, all the earlier passes
8329                         // were darkened by fog already, and we should not add fog color
8330                         // (because the background was not darkened, there is no fog color
8331                         // that was lost behind it).
8332                         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]);
8333                 }
8334         }
8335
8336         return t->currentframe;
8337 }
8338
8339 rsurfacestate_t rsurface;
8340
8341 void RSurf_ActiveWorldEntity(void)
8342 {
8343         dp_model_t *model = r_refdef.scene.worldmodel;
8344         //if (rsurface.entity == r_refdef.scene.worldentity)
8345         //      return;
8346         rsurface.entity = r_refdef.scene.worldentity;
8347         rsurface.skeleton = NULL;
8348         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8349         rsurface.ent_skinnum = 0;
8350         rsurface.ent_qwskin = -1;
8351         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8352         rsurface.shadertime = r_refdef.scene.time;
8353         rsurface.matrix = identitymatrix;
8354         rsurface.inversematrix = identitymatrix;
8355         rsurface.matrixscale = 1;
8356         rsurface.inversematrixscale = 1;
8357         R_EntityMatrix(&identitymatrix);
8358         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8359         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8360         rsurface.fograngerecip = r_refdef.fograngerecip;
8361         rsurface.fogheightfade = r_refdef.fogheightfade;
8362         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8363         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8364         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8365         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8366         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8367         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8368         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8369         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8370         rsurface.colormod[3] = 1;
8371         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);
8372         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8373         rsurface.frameblend[0].lerp = 1;
8374         rsurface.ent_alttextures = false;
8375         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8376         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8377         rsurface.entityskeletaltransform3x4 = NULL;
8378         rsurface.entityskeletaltransform3x4buffer = NULL;
8379         rsurface.entityskeletaltransform3x4offset = 0;
8380         rsurface.entityskeletaltransform3x4size = 0;;
8381         rsurface.entityskeletalnumtransforms = 0;
8382         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8383         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8384         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8385         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8386         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8387         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8388         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8389         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8390         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8391         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8392         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8393         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8394         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8395         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8396         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8397         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8398         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8399         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8400         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8401         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8402         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8403         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8404         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8405         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8406         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8407         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8408         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8409         rsurface.modelelement3i = model->surfmesh.data_element3i;
8410         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8411         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8412         rsurface.modelelement3s = model->surfmesh.data_element3s;
8413         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8414         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8415         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8416         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8417         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8418         rsurface.modelsurfaces = model->data_surfaces;
8419         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8420         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8421         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8422         rsurface.modelgeneratedvertex = false;
8423         rsurface.batchgeneratedvertex = false;
8424         rsurface.batchfirstvertex = 0;
8425         rsurface.batchnumvertices = 0;
8426         rsurface.batchfirsttriangle = 0;
8427         rsurface.batchnumtriangles = 0;
8428         rsurface.batchvertex3f  = NULL;
8429         rsurface.batchvertex3f_vertexbuffer = NULL;
8430         rsurface.batchvertex3f_bufferoffset = 0;
8431         rsurface.batchsvector3f = NULL;
8432         rsurface.batchsvector3f_vertexbuffer = NULL;
8433         rsurface.batchsvector3f_bufferoffset = 0;
8434         rsurface.batchtvector3f = NULL;
8435         rsurface.batchtvector3f_vertexbuffer = NULL;
8436         rsurface.batchtvector3f_bufferoffset = 0;
8437         rsurface.batchnormal3f  = NULL;
8438         rsurface.batchnormal3f_vertexbuffer = NULL;
8439         rsurface.batchnormal3f_bufferoffset = 0;
8440         rsurface.batchlightmapcolor4f = NULL;
8441         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8442         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8443         rsurface.batchtexcoordtexture2f = NULL;
8444         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8445         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8446         rsurface.batchtexcoordlightmap2f = NULL;
8447         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8448         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8449         rsurface.batchskeletalindex4ub = NULL;
8450         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8451         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8452         rsurface.batchskeletalweight4ub = NULL;
8453         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8454         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8455         rsurface.batchvertexmesh = NULL;
8456         rsurface.batchvertexmesh_vertexbuffer = NULL;
8457         rsurface.batchvertexmesh_bufferoffset = 0;
8458         rsurface.batchelement3i = NULL;
8459         rsurface.batchelement3i_indexbuffer = NULL;
8460         rsurface.batchelement3i_bufferoffset = 0;
8461         rsurface.batchelement3s = NULL;
8462         rsurface.batchelement3s_indexbuffer = NULL;
8463         rsurface.batchelement3s_bufferoffset = 0;
8464         rsurface.passcolor4f = NULL;
8465         rsurface.passcolor4f_vertexbuffer = NULL;
8466         rsurface.passcolor4f_bufferoffset = 0;
8467         rsurface.forcecurrenttextureupdate = false;
8468 }
8469
8470 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8471 {
8472         dp_model_t *model = ent->model;
8473         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8474         //      return;
8475         rsurface.entity = (entity_render_t *)ent;
8476         rsurface.skeleton = ent->skeleton;
8477         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8478         rsurface.ent_skinnum = ent->skinnum;
8479         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;
8480         rsurface.ent_flags = ent->flags;
8481         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8482         rsurface.matrix = ent->matrix;
8483         rsurface.inversematrix = ent->inversematrix;
8484         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8485         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8486         R_EntityMatrix(&rsurface.matrix);
8487         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8488         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8489         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8490         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8491         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8492         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8493         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8494         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8495         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8496         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8497         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8498         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8499         rsurface.colormod[3] = ent->alpha;
8500         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8501         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8502         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8503         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8504         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8505         if (ent->model->brush.submodel && !prepass)
8506         {
8507                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8508                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8509         }
8510         // if the animcache code decided it should use the shader path, skip the deform step
8511         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8512         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8513         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8514         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8515         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8516         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8517         {
8518                 if (ent->animcache_vertex3f)
8519                 {
8520                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8521                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8522                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8523                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8524                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8525                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8526                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8527                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8528                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8529                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8530                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8531                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8532                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8533                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8534                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8535                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8536                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8537                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8538                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8539                 }
8540                 else if (wanttangents)
8541                 {
8542                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8543                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8544                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8545                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8546                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8547                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8548                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8549                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8550                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8551                         rsurface.modelvertexmesh = NULL;
8552                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8553                         rsurface.modelvertexmesh_bufferoffset = 0;
8554                         rsurface.modelvertex3f_vertexbuffer = NULL;
8555                         rsurface.modelvertex3f_bufferoffset = 0;
8556                         rsurface.modelvertex3f_vertexbuffer = 0;
8557                         rsurface.modelvertex3f_bufferoffset = 0;
8558                         rsurface.modelsvector3f_vertexbuffer = 0;
8559                         rsurface.modelsvector3f_bufferoffset = 0;
8560                         rsurface.modeltvector3f_vertexbuffer = 0;
8561                         rsurface.modeltvector3f_bufferoffset = 0;
8562                         rsurface.modelnormal3f_vertexbuffer = 0;
8563                         rsurface.modelnormal3f_bufferoffset = 0;
8564                 }
8565                 else if (wantnormals)
8566                 {
8567                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8568                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8569                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8570                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8571                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8572                         rsurface.modelsvector3f = NULL;
8573                         rsurface.modeltvector3f = NULL;
8574                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8575                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8576                         rsurface.modelvertexmesh = NULL;
8577                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8578                         rsurface.modelvertexmesh_bufferoffset = 0;
8579                         rsurface.modelvertex3f_vertexbuffer = NULL;
8580                         rsurface.modelvertex3f_bufferoffset = 0;
8581                         rsurface.modelvertex3f_vertexbuffer = 0;
8582                         rsurface.modelvertex3f_bufferoffset = 0;
8583                         rsurface.modelsvector3f_vertexbuffer = 0;
8584                         rsurface.modelsvector3f_bufferoffset = 0;
8585                         rsurface.modeltvector3f_vertexbuffer = 0;
8586                         rsurface.modeltvector3f_bufferoffset = 0;
8587                         rsurface.modelnormal3f_vertexbuffer = 0;
8588                         rsurface.modelnormal3f_bufferoffset = 0;
8589                 }
8590                 else
8591                 {
8592                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8593                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8594                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8595                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8596                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8597                         rsurface.modelsvector3f = NULL;
8598                         rsurface.modeltvector3f = NULL;
8599                         rsurface.modelnormal3f = NULL;
8600                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8601                         rsurface.modelvertexmesh = NULL;
8602                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8603                         rsurface.modelvertexmesh_bufferoffset = 0;
8604                         rsurface.modelvertex3f_vertexbuffer = NULL;
8605                         rsurface.modelvertex3f_bufferoffset = 0;
8606                         rsurface.modelvertex3f_vertexbuffer = 0;
8607                         rsurface.modelvertex3f_bufferoffset = 0;
8608                         rsurface.modelsvector3f_vertexbuffer = 0;
8609                         rsurface.modelsvector3f_bufferoffset = 0;
8610                         rsurface.modeltvector3f_vertexbuffer = 0;
8611                         rsurface.modeltvector3f_bufferoffset = 0;
8612                         rsurface.modelnormal3f_vertexbuffer = 0;
8613                         rsurface.modelnormal3f_bufferoffset = 0;
8614                 }
8615                 rsurface.modelgeneratedvertex = true;
8616         }
8617         else
8618         {
8619                 if (rsurface.entityskeletaltransform3x4)
8620                 {
8621                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8622                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8623                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8624                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8625                 }
8626                 else
8627                 {
8628                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8629                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8630                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8631                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8632                 }
8633                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8634                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8635                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8636                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8637                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8638                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8639                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8640                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8641                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8642                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8643                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8644                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8645                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8646                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8647                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8648                 rsurface.modelgeneratedvertex = false;
8649         }
8650         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8651         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8652         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8653         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8654         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8655         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8656         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8657         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8658         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8659         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8660         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8661         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8662         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8663         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8664         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8665         rsurface.modelelement3i = model->surfmesh.data_element3i;
8666         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8667         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8668         rsurface.modelelement3s = model->surfmesh.data_element3s;
8669         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8670         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8671         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8672         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8673         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8674         rsurface.modelsurfaces = model->data_surfaces;
8675         rsurface.batchgeneratedvertex = false;
8676         rsurface.batchfirstvertex = 0;
8677         rsurface.batchnumvertices = 0;
8678         rsurface.batchfirsttriangle = 0;
8679         rsurface.batchnumtriangles = 0;
8680         rsurface.batchvertex3f  = NULL;
8681         rsurface.batchvertex3f_vertexbuffer = NULL;
8682         rsurface.batchvertex3f_bufferoffset = 0;
8683         rsurface.batchsvector3f = NULL;
8684         rsurface.batchsvector3f_vertexbuffer = NULL;
8685         rsurface.batchsvector3f_bufferoffset = 0;
8686         rsurface.batchtvector3f = NULL;
8687         rsurface.batchtvector3f_vertexbuffer = NULL;
8688         rsurface.batchtvector3f_bufferoffset = 0;
8689         rsurface.batchnormal3f  = NULL;
8690         rsurface.batchnormal3f_vertexbuffer = NULL;
8691         rsurface.batchnormal3f_bufferoffset = 0;
8692         rsurface.batchlightmapcolor4f = NULL;
8693         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8694         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8695         rsurface.batchtexcoordtexture2f = NULL;
8696         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8697         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8698         rsurface.batchtexcoordlightmap2f = NULL;
8699         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8700         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8701         rsurface.batchskeletalindex4ub = NULL;
8702         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8703         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8704         rsurface.batchskeletalweight4ub = NULL;
8705         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8706         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8707         rsurface.batchvertexmesh = NULL;
8708         rsurface.batchvertexmesh_vertexbuffer = NULL;
8709         rsurface.batchvertexmesh_bufferoffset = 0;
8710         rsurface.batchelement3i = NULL;
8711         rsurface.batchelement3i_indexbuffer = NULL;
8712         rsurface.batchelement3i_bufferoffset = 0;
8713         rsurface.batchelement3s = NULL;
8714         rsurface.batchelement3s_indexbuffer = NULL;
8715         rsurface.batchelement3s_bufferoffset = 0;
8716         rsurface.passcolor4f = NULL;
8717         rsurface.passcolor4f_vertexbuffer = NULL;
8718         rsurface.passcolor4f_bufferoffset = 0;
8719         rsurface.forcecurrenttextureupdate = false;
8720 }
8721
8722 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)
8723 {
8724         rsurface.entity = r_refdef.scene.worldentity;
8725         rsurface.skeleton = NULL;
8726         rsurface.ent_skinnum = 0;
8727         rsurface.ent_qwskin = -1;
8728         rsurface.ent_flags = entflags;
8729         rsurface.shadertime = r_refdef.scene.time - shadertime;
8730         rsurface.modelnumvertices = numvertices;
8731         rsurface.modelnumtriangles = numtriangles;
8732         rsurface.matrix = *matrix;
8733         rsurface.inversematrix = *inversematrix;
8734         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8735         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8736         R_EntityMatrix(&rsurface.matrix);
8737         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8738         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8739         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8740         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8741         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8742         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8743         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8744         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8745         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8746         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8747         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8748         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8749         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);
8750         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8751         rsurface.frameblend[0].lerp = 1;
8752         rsurface.ent_alttextures = false;
8753         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8754         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8755         rsurface.entityskeletaltransform3x4 = NULL;
8756         rsurface.entityskeletaltransform3x4buffer = NULL;
8757         rsurface.entityskeletaltransform3x4offset = 0;
8758         rsurface.entityskeletaltransform3x4size = 0;
8759         rsurface.entityskeletalnumtransforms = 0;
8760         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8761         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8762         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8763         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8764         if (wanttangents)
8765         {
8766                 rsurface.modelvertex3f = (float *)vertex3f;
8767                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8768                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8769                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8770         }
8771         else if (wantnormals)
8772         {
8773                 rsurface.modelvertex3f = (float *)vertex3f;
8774                 rsurface.modelsvector3f = NULL;
8775                 rsurface.modeltvector3f = NULL;
8776                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8777         }
8778         else
8779         {
8780                 rsurface.modelvertex3f = (float *)vertex3f;
8781                 rsurface.modelsvector3f = NULL;
8782                 rsurface.modeltvector3f = NULL;
8783                 rsurface.modelnormal3f = NULL;
8784         }
8785         rsurface.modelvertexmesh = NULL;
8786         rsurface.modelvertexmesh_vertexbuffer = NULL;
8787         rsurface.modelvertexmesh_bufferoffset = 0;
8788         rsurface.modelvertex3f_vertexbuffer = 0;
8789         rsurface.modelvertex3f_bufferoffset = 0;
8790         rsurface.modelsvector3f_vertexbuffer = 0;
8791         rsurface.modelsvector3f_bufferoffset = 0;
8792         rsurface.modeltvector3f_vertexbuffer = 0;
8793         rsurface.modeltvector3f_bufferoffset = 0;
8794         rsurface.modelnormal3f_vertexbuffer = 0;
8795         rsurface.modelnormal3f_bufferoffset = 0;
8796         rsurface.modelgeneratedvertex = true;
8797         rsurface.modellightmapcolor4f  = (float *)color4f;
8798         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8799         rsurface.modellightmapcolor4f_bufferoffset = 0;
8800         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8801         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8802         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8803         rsurface.modeltexcoordlightmap2f  = NULL;
8804         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8805         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8806         rsurface.modelskeletalindex4ub = NULL;
8807         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8808         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8809         rsurface.modelskeletalweight4ub = NULL;
8810         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8811         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8812         rsurface.modelelement3i = (int *)element3i;
8813         rsurface.modelelement3i_indexbuffer = NULL;
8814         rsurface.modelelement3i_bufferoffset = 0;
8815         rsurface.modelelement3s = (unsigned short *)element3s;
8816         rsurface.modelelement3s_indexbuffer = NULL;
8817         rsurface.modelelement3s_bufferoffset = 0;
8818         rsurface.modellightmapoffsets = NULL;
8819         rsurface.modelsurfaces = NULL;
8820         rsurface.batchgeneratedvertex = false;
8821         rsurface.batchfirstvertex = 0;
8822         rsurface.batchnumvertices = 0;
8823         rsurface.batchfirsttriangle = 0;
8824         rsurface.batchnumtriangles = 0;
8825         rsurface.batchvertex3f  = NULL;
8826         rsurface.batchvertex3f_vertexbuffer = NULL;
8827         rsurface.batchvertex3f_bufferoffset = 0;
8828         rsurface.batchsvector3f = NULL;
8829         rsurface.batchsvector3f_vertexbuffer = NULL;
8830         rsurface.batchsvector3f_bufferoffset = 0;
8831         rsurface.batchtvector3f = NULL;
8832         rsurface.batchtvector3f_vertexbuffer = NULL;
8833         rsurface.batchtvector3f_bufferoffset = 0;
8834         rsurface.batchnormal3f  = NULL;
8835         rsurface.batchnormal3f_vertexbuffer = NULL;
8836         rsurface.batchnormal3f_bufferoffset = 0;
8837         rsurface.batchlightmapcolor4f = NULL;
8838         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8839         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8840         rsurface.batchtexcoordtexture2f = NULL;
8841         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8842         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8843         rsurface.batchtexcoordlightmap2f = NULL;
8844         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8845         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8846         rsurface.batchskeletalindex4ub = NULL;
8847         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8848         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8849         rsurface.batchskeletalweight4ub = NULL;
8850         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8851         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8852         rsurface.batchvertexmesh = NULL;
8853         rsurface.batchvertexmesh_vertexbuffer = NULL;
8854         rsurface.batchvertexmesh_bufferoffset = 0;
8855         rsurface.batchelement3i = NULL;
8856         rsurface.batchelement3i_indexbuffer = NULL;
8857         rsurface.batchelement3i_bufferoffset = 0;
8858         rsurface.batchelement3s = NULL;
8859         rsurface.batchelement3s_indexbuffer = NULL;
8860         rsurface.batchelement3s_bufferoffset = 0;
8861         rsurface.passcolor4f = NULL;
8862         rsurface.passcolor4f_vertexbuffer = NULL;
8863         rsurface.passcolor4f_bufferoffset = 0;
8864         rsurface.forcecurrenttextureupdate = true;
8865
8866         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8867         {
8868                 if ((wantnormals || wanttangents) && !normal3f)
8869                 {
8870                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8871                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8872                 }
8873                 if (wanttangents && !svector3f)
8874                 {
8875                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8876                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8877                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8878                 }
8879         }
8880 }
8881
8882 float RSurf_FogPoint(const float *v)
8883 {
8884         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8885         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8886         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8887         float FogHeightFade = r_refdef.fogheightfade;
8888         float fogfrac;
8889         unsigned int fogmasktableindex;
8890         if (r_refdef.fogplaneviewabove)
8891                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8892         else
8893                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8894         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8895         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8896 }
8897
8898 float RSurf_FogVertex(const float *v)
8899 {
8900         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8901         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8902         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8903         float FogHeightFade = rsurface.fogheightfade;
8904         float fogfrac;
8905         unsigned int fogmasktableindex;
8906         if (r_refdef.fogplaneviewabove)
8907                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8908         else
8909                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8910         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8911         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8912 }
8913
8914 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8915 {
8916         int i;
8917         for (i = 0;i < numelements;i++)
8918                 outelement3i[i] = inelement3i[i] + adjust;
8919 }
8920
8921 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8922 extern cvar_t gl_vbo;
8923 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8924 {
8925         int deformindex;
8926         int firsttriangle;
8927         int numtriangles;
8928         int firstvertex;
8929         int endvertex;
8930         int numvertices;
8931         int surfacefirsttriangle;
8932         int surfacenumtriangles;
8933         int surfacefirstvertex;
8934         int surfaceendvertex;
8935         int surfacenumvertices;
8936         int batchnumsurfaces = texturenumsurfaces;
8937         int batchnumvertices;
8938         int batchnumtriangles;
8939         int needsupdate;
8940         int i, j;
8941         qboolean gaps;
8942         qboolean dynamicvertex;
8943         float amplitude;
8944         float animpos;
8945         float scale;
8946         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8947         float waveparms[4];
8948         unsigned char *ub;
8949         q3shaderinfo_deform_t *deform;
8950         const msurface_t *surface, *firstsurface;
8951         r_vertexmesh_t *vertexmesh;
8952         if (!texturenumsurfaces)
8953                 return;
8954         // find vertex range of this surface batch
8955         gaps = false;
8956         firstsurface = texturesurfacelist[0];
8957         firsttriangle = firstsurface->num_firsttriangle;
8958         batchnumvertices = 0;
8959         batchnumtriangles = 0;
8960         firstvertex = endvertex = firstsurface->num_firstvertex;
8961         for (i = 0;i < texturenumsurfaces;i++)
8962         {
8963                 surface = texturesurfacelist[i];
8964                 if (surface != firstsurface + i)
8965                         gaps = true;
8966                 surfacefirstvertex = surface->num_firstvertex;
8967                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8968                 surfacenumvertices = surface->num_vertices;
8969                 surfacenumtriangles = surface->num_triangles;
8970                 if (firstvertex > surfacefirstvertex)
8971                         firstvertex = surfacefirstvertex;
8972                 if (endvertex < surfaceendvertex)
8973                         endvertex = surfaceendvertex;
8974                 batchnumvertices += surfacenumvertices;
8975                 batchnumtriangles += surfacenumtriangles;
8976         }
8977
8978         r_refdef.stats[r_stat_batch_batches]++;
8979         if (gaps)
8980                 r_refdef.stats[r_stat_batch_withgaps]++;
8981         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8982         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8983         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8984
8985         // we now know the vertex range used, and if there are any gaps in it
8986         rsurface.batchfirstvertex = firstvertex;
8987         rsurface.batchnumvertices = endvertex - firstvertex;
8988         rsurface.batchfirsttriangle = firsttriangle;
8989         rsurface.batchnumtriangles = batchnumtriangles;
8990
8991         // this variable holds flags for which properties have been updated that
8992         // may require regenerating vertexmesh array...
8993         needsupdate = 0;
8994
8995         // check if any dynamic vertex processing must occur
8996         dynamicvertex = false;
8997
8998         // a cvar to force the dynamic vertex path to be taken, for debugging
8999         if (r_batch_debugdynamicvertexpath.integer)
9000         {
9001                 if (!dynamicvertex)
9002                 {
9003                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9004                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9005                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9006                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9007                 }
9008                 dynamicvertex = true;
9009         }
9010
9011         // if there is a chance of animated vertex colors, it's a dynamic batch
9012         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9013         {
9014                 if (!dynamicvertex)
9015                 {
9016                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9017                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9018                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9019                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9020                 }
9021                 dynamicvertex = true;
9022                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9023         }
9024
9025         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9026         {
9027                 switch (deform->deform)
9028                 {
9029                 default:
9030                 case Q3DEFORM_PROJECTIONSHADOW:
9031                 case Q3DEFORM_TEXT0:
9032                 case Q3DEFORM_TEXT1:
9033                 case Q3DEFORM_TEXT2:
9034                 case Q3DEFORM_TEXT3:
9035                 case Q3DEFORM_TEXT4:
9036                 case Q3DEFORM_TEXT5:
9037                 case Q3DEFORM_TEXT6:
9038                 case Q3DEFORM_TEXT7:
9039                 case Q3DEFORM_NONE:
9040                         break;
9041                 case Q3DEFORM_AUTOSPRITE:
9042                         if (!dynamicvertex)
9043                         {
9044                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9045                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9046                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9047                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9048                         }
9049                         dynamicvertex = true;
9050                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9051                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9052                         break;
9053                 case Q3DEFORM_AUTOSPRITE2:
9054                         if (!dynamicvertex)
9055                         {
9056                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9057                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9058                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9059                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9060                         }
9061                         dynamicvertex = true;
9062                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9063                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9064                         break;
9065                 case Q3DEFORM_NORMAL:
9066                         if (!dynamicvertex)
9067                         {
9068                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9069                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9070                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9071                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9072                         }
9073                         dynamicvertex = true;
9074                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9075                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9076                         break;
9077                 case Q3DEFORM_WAVE:
9078                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9079                                 break; // if wavefunc is a nop, ignore this transform
9080                         if (!dynamicvertex)
9081                         {
9082                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9083                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9084                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9085                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9086                         }
9087                         dynamicvertex = true;
9088                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9089                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9090                         break;
9091                 case Q3DEFORM_BULGE:
9092                         if (!dynamicvertex)
9093                         {
9094                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9095                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9096                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9097                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9098                         }
9099                         dynamicvertex = true;
9100                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9101                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9102                         break;
9103                 case Q3DEFORM_MOVE:
9104                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9105                                 break; // if wavefunc is a nop, ignore this transform
9106                         if (!dynamicvertex)
9107                         {
9108                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9109                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9110                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9111                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9112                         }
9113                         dynamicvertex = true;
9114                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9115                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9116                         break;
9117                 }
9118         }
9119         switch(rsurface.texture->tcgen.tcgen)
9120         {
9121         default:
9122         case Q3TCGEN_TEXTURE:
9123                 break;
9124         case Q3TCGEN_LIGHTMAP:
9125                 if (!dynamicvertex)
9126                 {
9127                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9128                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9129                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9130                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9131                 }
9132                 dynamicvertex = true;
9133                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9134                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9135                 break;
9136         case Q3TCGEN_VECTOR:
9137                 if (!dynamicvertex)
9138                 {
9139                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9140                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9141                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9142                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9143                 }
9144                 dynamicvertex = true;
9145                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9146                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9147                 break;
9148         case Q3TCGEN_ENVIRONMENT:
9149                 if (!dynamicvertex)
9150                 {
9151                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9152                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9153                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9154                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9155                 }
9156                 dynamicvertex = true;
9157                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9158                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9159                 break;
9160         }
9161         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9162         {
9163                 if (!dynamicvertex)
9164                 {
9165                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9166                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9167                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9168                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9169                 }
9170                 dynamicvertex = true;
9171                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9172                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9173         }
9174
9175         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9176         {
9177                 if (!dynamicvertex)
9178                 {
9179                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9180                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9181                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9182                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9183                 }
9184                 dynamicvertex = true;
9185                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9186         }
9187
9188         // when the model data has no vertex buffer (dynamic mesh), we need to
9189         // eliminate gaps
9190         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9191                 batchneed |= BATCHNEED_NOGAPS;
9192
9193         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9194         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9195         // we ensure this by treating the vertex batch as dynamic...
9196         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9197         {
9198                 if (!dynamicvertex)
9199                 {
9200                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9201                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9202                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9203                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9204                 }
9205                 dynamicvertex = true;
9206         }
9207
9208         if (dynamicvertex)
9209         {
9210                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9211                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9212                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9213                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9214                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9215                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9216                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9217                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9218         }
9219
9220         // if needsupdate, we have to do a dynamic vertex batch for sure
9221         if (needsupdate & batchneed)
9222         {
9223                 if (!dynamicvertex)
9224                 {
9225                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9226                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9227                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9228                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9229                 }
9230                 dynamicvertex = true;
9231         }
9232
9233         // see if we need to build vertexmesh from arrays
9234         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9235         {
9236                 if (!dynamicvertex)
9237                 {
9238                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9239                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9240                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9241                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9242                 }
9243                 dynamicvertex = true;
9244         }
9245
9246         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9247         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9248                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9249
9250         rsurface.batchvertex3f = rsurface.modelvertex3f;
9251         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9252         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9253         rsurface.batchsvector3f = rsurface.modelsvector3f;
9254         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9255         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9256         rsurface.batchtvector3f = rsurface.modeltvector3f;
9257         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9258         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9259         rsurface.batchnormal3f = rsurface.modelnormal3f;
9260         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9261         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9262         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9263         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9264         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9265         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9266         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9267         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9268         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9269         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9270         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9271         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9272         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9273         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9274         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9275         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9276         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9277         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9278         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9279         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9280         rsurface.batchelement3i = rsurface.modelelement3i;
9281         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9282         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9283         rsurface.batchelement3s = rsurface.modelelement3s;
9284         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9285         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9286         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9287         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9288         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9289         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9290         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9291
9292         // if any dynamic vertex processing has to occur in software, we copy the
9293         // entire surface list together before processing to rebase the vertices
9294         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9295         //
9296         // if any gaps exist and we do not have a static vertex buffer, we have to
9297         // copy the surface list together to avoid wasting upload bandwidth on the
9298         // vertices in the gaps.
9299         //
9300         // if gaps exist and we have a static vertex buffer, we can choose whether
9301         // to combine the index buffer ranges into one dynamic index buffer or
9302         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9303         //
9304         // in many cases the batch is reduced to one draw call.
9305
9306         rsurface.batchmultidraw = false;
9307         rsurface.batchmultidrawnumsurfaces = 0;
9308         rsurface.batchmultidrawsurfacelist = NULL;
9309
9310         if (!dynamicvertex)
9311         {
9312                 // static vertex data, just set pointers...
9313                 rsurface.batchgeneratedvertex = false;
9314                 // if there are gaps, we want to build a combined index buffer,
9315                 // otherwise use the original static buffer with an appropriate offset
9316                 if (gaps)
9317                 {
9318                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9319                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9320                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9321                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9322                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9323                         {
9324                                 rsurface.batchmultidraw = true;
9325                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9326                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9327                                 return;
9328                         }
9329                         // build a new triangle elements array for this batch
9330                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9331                         rsurface.batchfirsttriangle = 0;
9332                         numtriangles = 0;
9333                         for (i = 0;i < texturenumsurfaces;i++)
9334                         {
9335                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9336                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9337                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9338                                 numtriangles += surfacenumtriangles;
9339                         }
9340                         rsurface.batchelement3i_indexbuffer = NULL;
9341                         rsurface.batchelement3i_bufferoffset = 0;
9342                         rsurface.batchelement3s = NULL;
9343                         rsurface.batchelement3s_indexbuffer = NULL;
9344                         rsurface.batchelement3s_bufferoffset = 0;
9345                         if (endvertex <= 65536)
9346                         {
9347                                 // make a 16bit (unsigned short) index array if possible
9348                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9349                                 for (i = 0;i < numtriangles*3;i++)
9350                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9351                         }
9352                         // upload buffer data for the copytriangles batch
9353                         if (vid.forcevbo || (r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object))
9354                         {
9355                                 if (rsurface.batchelement3s)
9356                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9357                                 else if (rsurface.batchelement3i)
9358                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9359                         }
9360                 }
9361                 else
9362                 {
9363                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9364                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9365                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9366                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9367                 }
9368                 return;
9369         }
9370
9371         // something needs software processing, do it for real...
9372         // we only directly handle separate array data in this case and then
9373         // generate interleaved data if needed...
9374         rsurface.batchgeneratedvertex = true;
9375         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9376         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9377         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9378         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9379
9380         // now copy the vertex data into a combined array and make an index array
9381         // (this is what Quake3 does all the time)
9382         // we also apply any skeletal animation here that would have been done in
9383         // the vertex shader, because most of the dynamic vertex animation cases
9384         // need actual vertex positions and normals
9385         //if (dynamicvertex)
9386         {
9387                 rsurface.batchvertexmesh = NULL;
9388                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9389                 rsurface.batchvertexmesh_bufferoffset = 0;
9390                 rsurface.batchvertex3f = NULL;
9391                 rsurface.batchvertex3f_vertexbuffer = NULL;
9392                 rsurface.batchvertex3f_bufferoffset = 0;
9393                 rsurface.batchsvector3f = NULL;
9394                 rsurface.batchsvector3f_vertexbuffer = NULL;
9395                 rsurface.batchsvector3f_bufferoffset = 0;
9396                 rsurface.batchtvector3f = NULL;
9397                 rsurface.batchtvector3f_vertexbuffer = NULL;
9398                 rsurface.batchtvector3f_bufferoffset = 0;
9399                 rsurface.batchnormal3f = NULL;
9400                 rsurface.batchnormal3f_vertexbuffer = NULL;
9401                 rsurface.batchnormal3f_bufferoffset = 0;
9402                 rsurface.batchlightmapcolor4f = NULL;
9403                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9404                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9405                 rsurface.batchtexcoordtexture2f = NULL;
9406                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9407                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9408                 rsurface.batchtexcoordlightmap2f = NULL;
9409                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9410                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9411                 rsurface.batchskeletalindex4ub = NULL;
9412                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9413                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9414                 rsurface.batchskeletalweight4ub = NULL;
9415                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9416                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9417                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9418                 rsurface.batchelement3i_indexbuffer = NULL;
9419                 rsurface.batchelement3i_bufferoffset = 0;
9420                 rsurface.batchelement3s = NULL;
9421                 rsurface.batchelement3s_indexbuffer = NULL;
9422                 rsurface.batchelement3s_bufferoffset = 0;
9423                 rsurface.batchskeletaltransform3x4buffer = NULL;
9424                 rsurface.batchskeletaltransform3x4offset = 0;
9425                 rsurface.batchskeletaltransform3x4size = 0;
9426                 // we'll only be setting up certain arrays as needed
9427                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9428                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9429                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9430                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9431                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9432                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9433                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9434                 {
9435                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9436                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9437                 }
9438                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9439                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9440                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9441                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9442                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9443                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9444                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9445                 {
9446                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9447                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9448                 }
9449                 numvertices = 0;
9450                 numtriangles = 0;
9451                 for (i = 0;i < texturenumsurfaces;i++)
9452                 {
9453                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9454                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9455                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9456                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9457                         // copy only the data requested
9458                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9459                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9460                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9461                         {
9462                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9463                                 {
9464                                         if (rsurface.batchvertex3f)
9465                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9466                                         else
9467                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9468                                 }
9469                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9470                                 {
9471                                         if (rsurface.modelnormal3f)
9472                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9473                                         else
9474                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9475                                 }
9476                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9477                                 {
9478                                         if (rsurface.modelsvector3f)
9479                                         {
9480                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9481                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9482                                         }
9483                                         else
9484                                         {
9485                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9486                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9487                                         }
9488                                 }
9489                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9490                                 {
9491                                         if (rsurface.modellightmapcolor4f)
9492                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9493                                         else
9494                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9495                                 }
9496                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9497                                 {
9498                                         if (rsurface.modeltexcoordtexture2f)
9499                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9500                                         else
9501                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9502                                 }
9503                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9504                                 {
9505                                         if (rsurface.modeltexcoordlightmap2f)
9506                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9507                                         else
9508                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9509                                 }
9510                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9511                                 {
9512                                         if (rsurface.modelskeletalindex4ub)
9513                                         {
9514                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9515                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9516                                         }
9517                                         else
9518                                         {
9519                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9520                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9521                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9522                                                 for (j = 0;j < surfacenumvertices;j++)
9523                                                         ub[j*4] = 255;
9524                                         }
9525                                 }
9526                         }
9527                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9528                         numvertices += surfacenumvertices;
9529                         numtriangles += surfacenumtriangles;
9530                 }
9531
9532                 // generate a 16bit index array as well if possible
9533                 // (in general, dynamic batches fit)
9534                 if (numvertices <= 65536)
9535                 {
9536                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9537                         for (i = 0;i < numtriangles*3;i++)
9538                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9539                 }
9540
9541                 // since we've copied everything, the batch now starts at 0
9542                 rsurface.batchfirstvertex = 0;
9543                 rsurface.batchnumvertices = batchnumvertices;
9544                 rsurface.batchfirsttriangle = 0;
9545                 rsurface.batchnumtriangles = batchnumtriangles;
9546         }
9547
9548         // apply skeletal animation that would have been done in the vertex shader
9549         if (rsurface.batchskeletaltransform3x4)
9550         {
9551                 const unsigned char *si;
9552                 const unsigned char *sw;
9553                 const float *t[4];
9554                 const float *b = rsurface.batchskeletaltransform3x4;
9555                 float *vp, *vs, *vt, *vn;
9556                 float w[4];
9557                 float m[3][4], n[3][4];
9558                 float tp[3], ts[3], tt[3], tn[3];
9559                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9560                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9561                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9562                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9563                 si = rsurface.batchskeletalindex4ub;
9564                 sw = rsurface.batchskeletalweight4ub;
9565                 vp = rsurface.batchvertex3f;
9566                 vs = rsurface.batchsvector3f;
9567                 vt = rsurface.batchtvector3f;
9568                 vn = rsurface.batchnormal3f;
9569                 memset(m[0], 0, sizeof(m));
9570                 memset(n[0], 0, sizeof(n));
9571                 for (i = 0;i < batchnumvertices;i++)
9572                 {
9573                         t[0] = b + si[0]*12;
9574                         if (sw[0] == 255)
9575                         {
9576                                 // common case - only one matrix
9577                                 m[0][0] = t[0][ 0];
9578                                 m[0][1] = t[0][ 1];
9579                                 m[0][2] = t[0][ 2];
9580                                 m[0][3] = t[0][ 3];
9581                                 m[1][0] = t[0][ 4];
9582                                 m[1][1] = t[0][ 5];
9583                                 m[1][2] = t[0][ 6];
9584                                 m[1][3] = t[0][ 7];
9585                                 m[2][0] = t[0][ 8];
9586                                 m[2][1] = t[0][ 9];
9587                                 m[2][2] = t[0][10];
9588                                 m[2][3] = t[0][11];
9589                         }
9590                         else if (sw[2] + sw[3])
9591                         {
9592                                 // blend 4 matrices
9593                                 t[1] = b + si[1]*12;
9594                                 t[2] = b + si[2]*12;
9595                                 t[3] = b + si[3]*12;
9596                                 w[0] = sw[0] * (1.0f / 255.0f);
9597                                 w[1] = sw[1] * (1.0f / 255.0f);
9598                                 w[2] = sw[2] * (1.0f / 255.0f);
9599                                 w[3] = sw[3] * (1.0f / 255.0f);
9600                                 // blend the matrices
9601                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9602                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9603                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9604                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9605                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9606                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9607                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9608                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9609                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9610                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9611                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9612                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9613                         }
9614                         else
9615                         {
9616                                 // blend 2 matrices
9617                                 t[1] = b + si[1]*12;
9618                                 w[0] = sw[0] * (1.0f / 255.0f);
9619                                 w[1] = sw[1] * (1.0f / 255.0f);
9620                                 // blend the matrices
9621                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9622                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9623                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9624                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9625                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9626                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9627                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9628                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9629                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9630                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9631                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9632                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9633                         }
9634                         si += 4;
9635                         sw += 4;
9636                         // modify the vertex
9637                         VectorCopy(vp, tp);
9638                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9639                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9640                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9641                         vp += 3;
9642                         if (vn)
9643                         {
9644                                 // the normal transformation matrix is a set of cross products...
9645                                 CrossProduct(m[1], m[2], n[0]);
9646                                 CrossProduct(m[2], m[0], n[1]);
9647                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9648                                 VectorCopy(vn, tn);
9649                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9650                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9651                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9652                                 VectorNormalize(vn);
9653                                 vn += 3;
9654                                 if (vs)
9655                                 {
9656                                         VectorCopy(vs, ts);
9657                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9658                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9659                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9660                                         VectorNormalize(vs);
9661                                         vs += 3;
9662                                         VectorCopy(vt, tt);
9663                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9664                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9665                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9666                                         VectorNormalize(vt);
9667                                         vt += 3;
9668                                 }
9669                         }
9670                 }
9671                 rsurface.batchskeletaltransform3x4 = NULL;
9672                 rsurface.batchskeletalnumtransforms = 0;
9673         }
9674
9675         // q1bsp surfaces rendered in vertex color mode have to have colors
9676         // calculated based on lightstyles
9677         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9678         {
9679                 // generate color arrays for the surfaces in this list
9680                 int c[4];
9681                 int scale;
9682                 int size3;
9683                 const int *offsets;
9684                 const unsigned char *lm;
9685                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9686                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9687                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9688                 numvertices = 0;
9689                 for (i = 0;i < texturenumsurfaces;i++)
9690                 {
9691                         surface = texturesurfacelist[i];
9692                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9693                         surfacenumvertices = surface->num_vertices;
9694                         if (surface->lightmapinfo->samples)
9695                         {
9696                                 for (j = 0;j < surfacenumvertices;j++)
9697                                 {
9698                                         lm = surface->lightmapinfo->samples + offsets[j];
9699                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9700                                         VectorScale(lm, scale, c);
9701                                         if (surface->lightmapinfo->styles[1] != 255)
9702                                         {
9703                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9704                                                 lm += size3;
9705                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9706                                                 VectorMA(c, scale, lm, c);
9707                                                 if (surface->lightmapinfo->styles[2] != 255)
9708                                                 {
9709                                                         lm += size3;
9710                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9711                                                         VectorMA(c, scale, lm, c);
9712                                                         if (surface->lightmapinfo->styles[3] != 255)
9713                                                         {
9714                                                                 lm += size3;
9715                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9716                                                                 VectorMA(c, scale, lm, c);
9717                                                         }
9718                                                 }
9719                                         }
9720                                         c[0] >>= 7;
9721                                         c[1] >>= 7;
9722                                         c[2] >>= 7;
9723                                         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);
9724                                         numvertices++;
9725                                 }
9726                         }
9727                         else
9728                         {
9729                                 for (j = 0;j < surfacenumvertices;j++)
9730                                 {
9731                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9732                                         numvertices++;
9733                                 }
9734                         }
9735                 }
9736         }
9737
9738         // if vertices are deformed (sprite flares and things in maps, possibly
9739         // water waves, bulges and other deformations), modify the copied vertices
9740         // in place
9741         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9742         {
9743                 switch (deform->deform)
9744                 {
9745                 default:
9746                 case Q3DEFORM_PROJECTIONSHADOW:
9747                 case Q3DEFORM_TEXT0:
9748                 case Q3DEFORM_TEXT1:
9749                 case Q3DEFORM_TEXT2:
9750                 case Q3DEFORM_TEXT3:
9751                 case Q3DEFORM_TEXT4:
9752                 case Q3DEFORM_TEXT5:
9753                 case Q3DEFORM_TEXT6:
9754                 case Q3DEFORM_TEXT7:
9755                 case Q3DEFORM_NONE:
9756                         break;
9757                 case Q3DEFORM_AUTOSPRITE:
9758                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9759                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9760                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9761                         VectorNormalize(newforward);
9762                         VectorNormalize(newright);
9763                         VectorNormalize(newup);
9764 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9765 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9766 //                      rsurface.batchvertex3f_bufferoffset = 0;
9767 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9768 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9769 //                      rsurface.batchsvector3f_bufferoffset = 0;
9770 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9771 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9772 //                      rsurface.batchtvector3f_bufferoffset = 0;
9773 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9774 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9775 //                      rsurface.batchnormal3f_bufferoffset = 0;
9776                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9777                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9778                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9779                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9780                                 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);
9781                         // a single autosprite surface can contain multiple sprites...
9782                         for (j = 0;j < batchnumvertices - 3;j += 4)
9783                         {
9784                                 VectorClear(center);
9785                                 for (i = 0;i < 4;i++)
9786                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9787                                 VectorScale(center, 0.25f, center);
9788                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9789                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9790                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9791                                 for (i = 0;i < 4;i++)
9792                                 {
9793                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9794                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9795                                 }
9796                         }
9797                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9798                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9799                         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);
9800                         break;
9801                 case Q3DEFORM_AUTOSPRITE2:
9802                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9803                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9804                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9805                         VectorNormalize(newforward);
9806                         VectorNormalize(newright);
9807                         VectorNormalize(newup);
9808 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9809 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9810 //                      rsurface.batchvertex3f_bufferoffset = 0;
9811                         {
9812                                 const float *v1, *v2;
9813                                 vec3_t start, end;
9814                                 float f, l;
9815                                 struct
9816                                 {
9817                                         float length2;
9818                                         const float *v1;
9819                                         const float *v2;
9820                                 }
9821                                 shortest[2];
9822                                 memset(shortest, 0, sizeof(shortest));
9823                                 // a single autosprite surface can contain multiple sprites...
9824                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9825                                 {
9826                                         VectorClear(center);
9827                                         for (i = 0;i < 4;i++)
9828                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9829                                         VectorScale(center, 0.25f, center);
9830                                         // find the two shortest edges, then use them to define the
9831                                         // axis vectors for rotating around the central axis
9832                                         for (i = 0;i < 6;i++)
9833                                         {
9834                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9835                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9836                                                 l = VectorDistance2(v1, v2);
9837                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9838                                                 if (v1[2] != v2[2])
9839                                                         l += (1.0f / 1024.0f);
9840                                                 if (shortest[0].length2 > l || i == 0)
9841                                                 {
9842                                                         shortest[1] = shortest[0];
9843                                                         shortest[0].length2 = l;
9844                                                         shortest[0].v1 = v1;
9845                                                         shortest[0].v2 = v2;
9846                                                 }
9847                                                 else if (shortest[1].length2 > l || i == 1)
9848                                                 {
9849                                                         shortest[1].length2 = l;
9850                                                         shortest[1].v1 = v1;
9851                                                         shortest[1].v2 = v2;
9852                                                 }
9853                                         }
9854                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9855                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9856                                         // this calculates the right vector from the shortest edge
9857                                         // and the up vector from the edge midpoints
9858                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9859                                         VectorNormalize(right);
9860                                         VectorSubtract(end, start, up);
9861                                         VectorNormalize(up);
9862                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9863                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9864                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9865                                         VectorNegate(forward, forward);
9866                                         VectorReflect(forward, 0, up, forward);
9867                                         VectorNormalize(forward);
9868                                         CrossProduct(up, forward, newright);
9869                                         VectorNormalize(newright);
9870                                         // rotate the quad around the up axis vector, this is made
9871                                         // especially easy by the fact we know the quad is flat,
9872                                         // so we only have to subtract the center position and
9873                                         // measure distance along the right vector, and then
9874                                         // multiply that by the newright vector and add back the
9875                                         // center position
9876                                         // we also need to subtract the old position to undo the
9877                                         // displacement from the center, which we do with a
9878                                         // DotProduct, the subtraction/addition of center is also
9879                                         // optimized into DotProducts here
9880                                         l = DotProduct(right, center);
9881                                         for (i = 0;i < 4;i++)
9882                                         {
9883                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9884                                                 f = DotProduct(right, v1) - l;
9885                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9886                                         }
9887                                 }
9888                         }
9889                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9890                         {
9891 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9892 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9893 //                              rsurface.batchnormal3f_bufferoffset = 0;
9894                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9895                         }
9896                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9897                         {
9898 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9899 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9900 //                              rsurface.batchsvector3f_bufferoffset = 0;
9901 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9902 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9903 //                              rsurface.batchtvector3f_bufferoffset = 0;
9904                                 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);
9905                         }
9906                         break;
9907                 case Q3DEFORM_NORMAL:
9908                         // deform the normals to make reflections wavey
9909                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9910                         rsurface.batchnormal3f_vertexbuffer = NULL;
9911                         rsurface.batchnormal3f_bufferoffset = 0;
9912                         for (j = 0;j < batchnumvertices;j++)
9913                         {
9914                                 float vertex[3];
9915                                 float *normal = rsurface.batchnormal3f + 3*j;
9916                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9917                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9918                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9919                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9920                                 VectorNormalize(normal);
9921                         }
9922                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9923                         {
9924 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9925 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9926 //                              rsurface.batchsvector3f_bufferoffset = 0;
9927 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9928 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9929 //                              rsurface.batchtvector3f_bufferoffset = 0;
9930                                 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);
9931                         }
9932                         break;
9933                 case Q3DEFORM_WAVE:
9934                         // deform vertex array to make wavey water and flags and such
9935                         waveparms[0] = deform->waveparms[0];
9936                         waveparms[1] = deform->waveparms[1];
9937                         waveparms[2] = deform->waveparms[2];
9938                         waveparms[3] = deform->waveparms[3];
9939                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9940                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9941                         // this is how a divisor of vertex influence on deformation
9942                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9943                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9944 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9945 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9946 //                      rsurface.batchvertex3f_bufferoffset = 0;
9947 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9948 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9949 //                      rsurface.batchnormal3f_bufferoffset = 0;
9950                         for (j = 0;j < batchnumvertices;j++)
9951                         {
9952                                 // if the wavefunc depends on time, evaluate it per-vertex
9953                                 if (waveparms[3])
9954                                 {
9955                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9956                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9957                                 }
9958                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9959                         }
9960                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9961                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9962                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9963                         {
9964 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9965 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9966 //                              rsurface.batchsvector3f_bufferoffset = 0;
9967 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9968 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9969 //                              rsurface.batchtvector3f_bufferoffset = 0;
9970                                 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);
9971                         }
9972                         break;
9973                 case Q3DEFORM_BULGE:
9974                         // deform vertex array to make the surface have moving bulges
9975 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9976 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9977 //                      rsurface.batchvertex3f_bufferoffset = 0;
9978 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9979 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9980 //                      rsurface.batchnormal3f_bufferoffset = 0;
9981                         for (j = 0;j < batchnumvertices;j++)
9982                         {
9983                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9984                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9985                         }
9986                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9987                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9988                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9989                         {
9990 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9991 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9992 //                              rsurface.batchsvector3f_bufferoffset = 0;
9993 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9994 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9995 //                              rsurface.batchtvector3f_bufferoffset = 0;
9996                                 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);
9997                         }
9998                         break;
9999                 case Q3DEFORM_MOVE:
10000                         // deform vertex array
10001                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10002                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10003                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10004                         VectorScale(deform->parms, scale, waveparms);
10005 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10006 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10007 //                      rsurface.batchvertex3f_bufferoffset = 0;
10008                         for (j = 0;j < batchnumvertices;j++)
10009                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10010                         break;
10011                 }
10012         }
10013
10014         // generate texcoords based on the chosen texcoord source
10015         switch(rsurface.texture->tcgen.tcgen)
10016         {
10017         default:
10018         case Q3TCGEN_TEXTURE:
10019                 break;
10020         case Q3TCGEN_LIGHTMAP:
10021 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10022 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10023 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10024                 if (rsurface.batchtexcoordlightmap2f)
10025                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
10026                 break;
10027         case Q3TCGEN_VECTOR:
10028 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10029 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10030 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10031                 for (j = 0;j < batchnumvertices;j++)
10032                 {
10033                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10034                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10035                 }
10036                 break;
10037         case Q3TCGEN_ENVIRONMENT:
10038                 // make environment reflections using a spheremap
10039                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10040                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10041                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10042                 for (j = 0;j < batchnumvertices;j++)
10043                 {
10044                         // identical to Q3A's method, but executed in worldspace so
10045                         // carried models can be shiny too
10046
10047                         float viewer[3], d, reflected[3], worldreflected[3];
10048
10049                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10050                         // VectorNormalize(viewer);
10051
10052                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10053
10054                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10055                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10056                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10057                         // note: this is proportinal to viewer, so we can normalize later
10058
10059                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10060                         VectorNormalize(worldreflected);
10061
10062                         // note: this sphere map only uses world x and z!
10063                         // so positive and negative y will LOOK THE SAME.
10064                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10065                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10066                 }
10067                 break;
10068         }
10069         // the only tcmod that needs software vertex processing is turbulent, so
10070         // check for it here and apply the changes if needed
10071         // and we only support that as the first one
10072         // (handling a mixture of turbulent and other tcmods would be problematic
10073         //  without punting it entirely to a software path)
10074         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10075         {
10076                 amplitude = rsurface.texture->tcmods[0].parms[1];
10077                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10078 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10079 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10080 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10081                 for (j = 0;j < batchnumvertices;j++)
10082                 {
10083                         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);
10084                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10085                 }
10086         }
10087
10088         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10089         {
10090                 // convert the modified arrays to vertex structs
10091 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10092 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10093 //              rsurface.batchvertexmesh_bufferoffset = 0;
10094                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10095                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10096                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10097                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10098                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10099                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10100                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10101                 {
10102                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10103                         {
10104                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10105                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10106                         }
10107                 }
10108                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10109                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10110                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10111                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10112                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10113                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10114                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10115                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10116                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10117                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10118                 {
10119                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10120                         {
10121                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10122                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10123                         }
10124                 }
10125         }
10126
10127         // upload buffer data for the dynamic batch
10128         if (vid.forcevbo || (r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object))
10129         {
10130                 if (rsurface.batchvertexmesh)
10131                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10132                 else
10133                 {
10134                         if (rsurface.batchvertex3f)
10135                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10136                         if (rsurface.batchsvector3f)
10137                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10138                         if (rsurface.batchtvector3f)
10139                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10140                         if (rsurface.batchnormal3f)
10141                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10142                         if (rsurface.batchlightmapcolor4f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
10143                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10144                         if (rsurface.batchtexcoordtexture2f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
10145                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10146                         if (rsurface.batchtexcoordlightmap2f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
10147                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10148                         if (rsurface.batchskeletalindex4ub)
10149                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10150                         if (rsurface.batchskeletalweight4ub)
10151                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10152                 }
10153                 if (rsurface.batchelement3s)
10154                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10155                 else if (rsurface.batchelement3i)
10156                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10157         }
10158 }
10159
10160 void RSurf_DrawBatch(void)
10161 {
10162         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10163         // through the pipeline, killing it earlier in the pipeline would have
10164         // per-surface overhead rather than per-batch overhead, so it's best to
10165         // reject it here, before it hits glDraw.
10166         if (rsurface.batchnumtriangles == 0)
10167                 return;
10168 #if 0
10169         // batch debugging code
10170         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10171         {
10172                 int i;
10173                 int j;
10174                 int c;
10175                 const int *e;
10176                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10177                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10178                 {
10179                         c = e[i];
10180                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10181                         {
10182                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10183                                 {
10184                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10185                                                 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);
10186                                         break;
10187                                 }
10188                         }
10189                 }
10190         }
10191 #endif
10192         if (rsurface.batchmultidraw)
10193         {
10194                 // issue multiple draws rather than copying index data
10195                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10196                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10197                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10198                 for (i = 0;i < numsurfaces;)
10199                 {
10200                         // combine consecutive surfaces as one draw
10201                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10202                                 if (surfacelist[j] != surfacelist[k] + 1)
10203                                         break;
10204                         firstvertex = surfacelist[i]->num_firstvertex;
10205                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10206                         firsttriangle = surfacelist[i]->num_firsttriangle;
10207                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10208                         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);
10209                         i = j;
10210                 }
10211         }
10212         else
10213         {
10214                 // there is only one consecutive run of index data (may have been combined)
10215                 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);
10216         }
10217 }
10218
10219 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10220 {
10221         // pick the closest matching water plane
10222         int planeindex, vertexindex, bestplaneindex = -1;
10223         float d, bestd;
10224         vec3_t vert;
10225         const float *v;
10226         r_waterstate_waterplane_t *p;
10227         qboolean prepared = false;
10228         bestd = 0;
10229         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10230         {
10231                 if(p->camera_entity != rsurface.texture->camera_entity)
10232                         continue;
10233                 d = 0;
10234                 if(!prepared)
10235                 {
10236                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10237                         prepared = true;
10238                         if(rsurface.batchnumvertices == 0)
10239                                 break;
10240                 }
10241                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10242                 {
10243                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10244                         d += fabs(PlaneDiff(vert, &p->plane));
10245                 }
10246                 if (bestd > d || bestplaneindex < 0)
10247                 {
10248                         bestd = d;
10249                         bestplaneindex = planeindex;
10250                 }
10251         }
10252         return bestplaneindex;
10253         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10254         // this situation though, as it might be better to render single larger
10255         // batches with useless stuff (backface culled for example) than to
10256         // render multiple smaller batches
10257 }
10258
10259 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10260 {
10261         int i;
10262         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10263         rsurface.passcolor4f_vertexbuffer = 0;
10264         rsurface.passcolor4f_bufferoffset = 0;
10265         for (i = 0;i < rsurface.batchnumvertices;i++)
10266                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10267 }
10268
10269 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10270 {
10271         int i;
10272         float f;
10273         const float *v;
10274         const float *c;
10275         float *c2;
10276         if (rsurface.passcolor4f)
10277         {
10278                 // generate color arrays
10279                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10280                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10281                 rsurface.passcolor4f_vertexbuffer = 0;
10282                 rsurface.passcolor4f_bufferoffset = 0;
10283                 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)
10284                 {
10285                         f = RSurf_FogVertex(v);
10286                         c2[0] = c[0] * f;
10287                         c2[1] = c[1] * f;
10288                         c2[2] = c[2] * f;
10289                         c2[3] = c[3];
10290                 }
10291         }
10292         else
10293         {
10294                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10295                 rsurface.passcolor4f_vertexbuffer = 0;
10296                 rsurface.passcolor4f_bufferoffset = 0;
10297                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10298                 {
10299                         f = RSurf_FogVertex(v);
10300                         c2[0] = f;
10301                         c2[1] = f;
10302                         c2[2] = f;
10303                         c2[3] = 1;
10304                 }
10305         }
10306 }
10307
10308 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10309 {
10310         int i;
10311         float f;
10312         const float *v;
10313         const float *c;
10314         float *c2;
10315         if (!rsurface.passcolor4f)
10316                 return;
10317         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10318         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10319         rsurface.passcolor4f_vertexbuffer = 0;
10320         rsurface.passcolor4f_bufferoffset = 0;
10321         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)
10322         {
10323                 f = RSurf_FogVertex(v);
10324                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10325                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10326                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10327                 c2[3] = c[3];
10328         }
10329 }
10330
10331 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10332 {
10333         int i;
10334         const float *c;
10335         float *c2;
10336         if (!rsurface.passcolor4f)
10337                 return;
10338         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10339         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10340         rsurface.passcolor4f_vertexbuffer = 0;
10341         rsurface.passcolor4f_bufferoffset = 0;
10342         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10343         {
10344                 c2[0] = c[0] * r;
10345                 c2[1] = c[1] * g;
10346                 c2[2] = c[2] * b;
10347                 c2[3] = c[3] * a;
10348         }
10349 }
10350
10351 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10352 {
10353         int i;
10354         const float *c;
10355         float *c2;
10356         if (!rsurface.passcolor4f)
10357                 return;
10358         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10359         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10360         rsurface.passcolor4f_vertexbuffer = 0;
10361         rsurface.passcolor4f_bufferoffset = 0;
10362         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10363         {
10364                 c2[0] = c[0] + r_refdef.scene.ambient;
10365                 c2[1] = c[1] + r_refdef.scene.ambient;
10366                 c2[2] = c[2] + r_refdef.scene.ambient;
10367                 c2[3] = c[3];
10368         }
10369 }
10370
10371 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10372 {
10373         // TODO: optimize
10374         rsurface.passcolor4f = NULL;
10375         rsurface.passcolor4f_vertexbuffer = 0;
10376         rsurface.passcolor4f_bufferoffset = 0;
10377         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10378         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10379         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10380         GL_Color(r, g, b, a);
10381         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10382         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10383         R_Mesh_TexMatrix(0, NULL);
10384         RSurf_DrawBatch();
10385 }
10386
10387 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10388 {
10389         // TODO: optimize applyfog && applycolor case
10390         // just apply fog if necessary, and tint the fog color array if necessary
10391         rsurface.passcolor4f = NULL;
10392         rsurface.passcolor4f_vertexbuffer = 0;
10393         rsurface.passcolor4f_bufferoffset = 0;
10394         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10395         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10396         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10397         GL_Color(r, g, b, a);
10398         RSurf_DrawBatch();
10399 }
10400
10401 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10402 {
10403         // TODO: optimize
10404         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10405         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10406         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10407         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10408         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10409         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10410         GL_Color(r, g, b, a);
10411         RSurf_DrawBatch();
10412 }
10413
10414 static void RSurf_DrawBatch_GL11_ClampColor(void)
10415 {
10416         int i;
10417         const float *c1;
10418         float *c2;
10419         if (!rsurface.passcolor4f)
10420                 return;
10421         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10422         {
10423                 c2[0] = bound(0.0f, c1[0], 1.0f);
10424                 c2[1] = bound(0.0f, c1[1], 1.0f);
10425                 c2[2] = bound(0.0f, c1[2], 1.0f);
10426                 c2[3] = bound(0.0f, c1[3], 1.0f);
10427         }
10428 }
10429
10430 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10431 {
10432         int i;
10433         float f;
10434         const float *v;
10435         const float *n;
10436         float *c;
10437         //vec3_t eyedir;
10438
10439         // fake shading
10440         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10441         rsurface.passcolor4f_vertexbuffer = 0;
10442         rsurface.passcolor4f_bufferoffset = 0;
10443         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)
10444         {
10445                 f = -DotProduct(r_refdef.view.forward, n);
10446                 f = max(0, f);
10447                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10448                 f *= r_refdef.lightmapintensity;
10449                 Vector4Set(c, f, f, f, 1);
10450         }
10451 }
10452
10453 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10454 {
10455         RSurf_DrawBatch_GL11_ApplyFakeLight();
10456         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10457         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10458         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10459         GL_Color(r, g, b, a);
10460         RSurf_DrawBatch();
10461 }
10462
10463 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10464 {
10465         int i;
10466         float f;
10467         float alpha;
10468         const float *v;
10469         const float *n;
10470         float *c;
10471         vec3_t ambientcolor;
10472         vec3_t diffusecolor;
10473         vec3_t lightdir;
10474         // TODO: optimize
10475         // model lighting
10476         VectorCopy(rsurface.modellight_lightdir, lightdir);
10477         f = 0.5f * r_refdef.lightmapintensity;
10478         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10479         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10480         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10481         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10482         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10483         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10484         alpha = *a;
10485         if (VectorLength2(diffusecolor) > 0)
10486         {
10487                 // q3-style directional shading
10488                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10489                 rsurface.passcolor4f_vertexbuffer = 0;
10490                 rsurface.passcolor4f_bufferoffset = 0;
10491                 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)
10492                 {
10493                         if ((f = DotProduct(n, lightdir)) > 0)
10494                                 VectorMA(ambientcolor, f, diffusecolor, c);
10495                         else
10496                                 VectorCopy(ambientcolor, c);
10497                         c[3] = alpha;
10498                 }
10499                 *r = 1;
10500                 *g = 1;
10501                 *b = 1;
10502                 *a = 1;
10503                 *applycolor = false;
10504         }
10505         else
10506         {
10507                 *r = ambientcolor[0];
10508                 *g = ambientcolor[1];
10509                 *b = ambientcolor[2];
10510                 rsurface.passcolor4f = NULL;
10511                 rsurface.passcolor4f_vertexbuffer = 0;
10512                 rsurface.passcolor4f_bufferoffset = 0;
10513         }
10514 }
10515
10516 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10517 {
10518         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10519         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10520         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10521         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10522         GL_Color(r, g, b, a);
10523         RSurf_DrawBatch();
10524 }
10525
10526 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10527 {
10528         int i;
10529         float f;
10530         const float *v;
10531         float *c;
10532
10533         // fake shading
10534         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10535         rsurface.passcolor4f_vertexbuffer = 0;
10536         rsurface.passcolor4f_bufferoffset = 0;
10537
10538         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10539         {
10540                 f = 1 - RSurf_FogVertex(v);
10541                 c[0] = r;
10542                 c[1] = g;
10543                 c[2] = b;
10544                 c[3] = f * a;
10545         }
10546 }
10547
10548 void RSurf_SetupDepthAndCulling(void)
10549 {
10550         // submodels are biased to avoid z-fighting with world surfaces that they
10551         // may be exactly overlapping (avoids z-fighting artifacts on certain
10552         // doors and things in Quake maps)
10553         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10554         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10555         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10556         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10557 }
10558
10559 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10560 {
10561         // transparent sky would be ridiculous
10562         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10563                 return;
10564         R_SetupShader_Generic_NoTexture(false, false);
10565         skyrenderlater = true;
10566         RSurf_SetupDepthAndCulling();
10567         GL_DepthMask(true);
10568         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10569         // skymasking on them, and Quake3 never did sky masking (unlike
10570         // software Quake and software Quake2), so disable the sky masking
10571         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10572         // and skymasking also looks very bad when noclipping outside the
10573         // level, so don't use it then either.
10574         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10575         {
10576                 R_Mesh_ResetTextureState();
10577                 if (skyrendermasked)
10578                 {
10579                         R_SetupShader_DepthOrShadow(false, false, false);
10580                         // depth-only (masking)
10581                         GL_ColorMask(0,0,0,0);
10582                         // just to make sure that braindead drivers don't draw
10583                         // anything despite that colormask...
10584                         GL_BlendFunc(GL_ZERO, GL_ONE);
10585                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10586                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10587                 }
10588                 else
10589                 {
10590                         R_SetupShader_Generic_NoTexture(false, false);
10591                         // fog sky
10592                         GL_BlendFunc(GL_ONE, GL_ZERO);
10593                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10594                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10595                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10596                 }
10597                 RSurf_DrawBatch();
10598                 if (skyrendermasked)
10599                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10600         }
10601         R_Mesh_ResetTextureState();
10602         GL_Color(1, 1, 1, 1);
10603 }
10604
10605 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10606 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10607 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10608 {
10609         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10610                 return;
10611         if (prepass)
10612         {
10613                 // render screenspace normalmap to texture
10614                 GL_DepthMask(true);
10615                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10616                 RSurf_DrawBatch();
10617                 return;
10618         }
10619
10620         // bind lightmap texture
10621
10622         // water/refraction/reflection/camera surfaces have to be handled specially
10623         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10624         {
10625                 int start, end, startplaneindex;
10626                 for (start = 0;start < texturenumsurfaces;start = end)
10627                 {
10628                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10629                         if(startplaneindex < 0)
10630                         {
10631                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10632                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10633                                 end = start + 1;
10634                                 continue;
10635                         }
10636                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10637                                 ;
10638                         // now that we have a batch using the same planeindex, render it
10639                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10640                         {
10641                                 // render water or distortion background
10642                                 GL_DepthMask(true);
10643                                 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);
10644                                 RSurf_DrawBatch();
10645                                 // blend surface on top
10646                                 GL_DepthMask(false);
10647                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10648                                 RSurf_DrawBatch();
10649                         }
10650                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10651                         {
10652                                 // render surface with reflection texture as input
10653                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10654                                 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);
10655                                 RSurf_DrawBatch();
10656                         }
10657                 }
10658                 return;
10659         }
10660
10661         // render surface batch normally
10662         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10663         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);
10664         RSurf_DrawBatch();
10665 }
10666
10667 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10668 {
10669         // OpenGL 1.3 path - anything not completely ancient
10670         qboolean applycolor;
10671         qboolean applyfog;
10672         int layerindex;
10673         const texturelayer_t *layer;
10674         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);
10675         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10676
10677         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10678         {
10679                 vec4_t layercolor;
10680                 int layertexrgbscale;
10681                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10682                 {
10683                         if (layerindex == 0)
10684                                 GL_AlphaTest(true);
10685                         else
10686                         {
10687                                 GL_AlphaTest(false);
10688                                 GL_DepthFunc(GL_EQUAL);
10689                         }
10690                 }
10691                 GL_DepthMask(layer->depthmask && writedepth);
10692                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10693                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10694                 {
10695                         layertexrgbscale = 4;
10696                         VectorScale(layer->color, 0.25f, layercolor);
10697                 }
10698                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10699                 {
10700                         layertexrgbscale = 2;
10701                         VectorScale(layer->color, 0.5f, layercolor);
10702                 }
10703                 else
10704                 {
10705                         layertexrgbscale = 1;
10706                         VectorScale(layer->color, 1.0f, layercolor);
10707                 }
10708                 layercolor[3] = layer->color[3];
10709                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10710                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10711                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10712                 switch (layer->type)
10713                 {
10714                 case TEXTURELAYERTYPE_LITTEXTURE:
10715                         // single-pass lightmapped texture with 2x rgbscale
10716                         R_Mesh_TexBind(0, r_texture_white);
10717                         R_Mesh_TexMatrix(0, NULL);
10718                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10719                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10720                         R_Mesh_TexBind(1, layer->texture);
10721                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10722                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10723                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10724                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10725                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10726                         else if (FAKELIGHT_ENABLED)
10727                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10728                         else if (rsurface.uselightmaptexture)
10729                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10730                         else
10731                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10732                         break;
10733                 case TEXTURELAYERTYPE_TEXTURE:
10734                         // singletexture unlit texture with transparency support
10735                         R_Mesh_TexBind(0, layer->texture);
10736                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10737                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10738                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10739                         R_Mesh_TexBind(1, 0);
10740                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10741                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10742                         break;
10743                 case TEXTURELAYERTYPE_FOG:
10744                         // singletexture fogging
10745                         if (layer->texture)
10746                         {
10747                                 R_Mesh_TexBind(0, layer->texture);
10748                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10749                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10750                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10751                         }
10752                         else
10753                         {
10754                                 R_Mesh_TexBind(0, 0);
10755                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10756                         }
10757                         R_Mesh_TexBind(1, 0);
10758                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10759                         // generate a color array for the fog pass
10760                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10761                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10762                         RSurf_DrawBatch();
10763                         break;
10764                 default:
10765                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10766                 }
10767         }
10768         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10769         {
10770                 GL_DepthFunc(GL_LEQUAL);
10771                 GL_AlphaTest(false);
10772         }
10773 }
10774
10775 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10776 {
10777         // OpenGL 1.1 - crusty old voodoo path
10778         qboolean applyfog;
10779         int layerindex;
10780         const texturelayer_t *layer;
10781         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);
10782         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10783
10784         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10785         {
10786                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10787                 {
10788                         if (layerindex == 0)
10789                                 GL_AlphaTest(true);
10790                         else
10791                         {
10792                                 GL_AlphaTest(false);
10793                                 GL_DepthFunc(GL_EQUAL);
10794                         }
10795                 }
10796                 GL_DepthMask(layer->depthmask && writedepth);
10797                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10798                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10799                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10800                 switch (layer->type)
10801                 {
10802                 case TEXTURELAYERTYPE_LITTEXTURE:
10803                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10804                         {
10805                                 // two-pass lit texture with 2x rgbscale
10806                                 // first the lightmap pass
10807                                 R_Mesh_TexBind(0, r_texture_white);
10808                                 R_Mesh_TexMatrix(0, NULL);
10809                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10810                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10811                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10812                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10813                                 else if (FAKELIGHT_ENABLED)
10814                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10815                                 else if (rsurface.uselightmaptexture)
10816                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10817                                 else
10818                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10819                                 // then apply the texture to it
10820                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10821                                 R_Mesh_TexBind(0, layer->texture);
10822                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10823                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10824                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10825                                 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);
10826                         }
10827                         else
10828                         {
10829                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10830                                 R_Mesh_TexBind(0, layer->texture);
10831                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10832                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10833                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10834                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10835                                         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);
10836                                 else if (FAKELIGHT_ENABLED)
10837                                         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);
10838                                 else
10839                                         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);
10840                         }
10841                         break;
10842                 case TEXTURELAYERTYPE_TEXTURE:
10843                         // singletexture unlit texture with transparency support
10844                         R_Mesh_TexBind(0, layer->texture);
10845                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10846                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10847                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10848                         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);
10849                         break;
10850                 case TEXTURELAYERTYPE_FOG:
10851                         // singletexture fogging
10852                         if (layer->texture)
10853                         {
10854                                 R_Mesh_TexBind(0, layer->texture);
10855                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10856                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10857                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10858                         }
10859                         else
10860                         {
10861                                 R_Mesh_TexBind(0, 0);
10862                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10863                         }
10864                         // generate a color array for the fog pass
10865                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10866                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10867                         RSurf_DrawBatch();
10868                         break;
10869                 default:
10870                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10871                 }
10872         }
10873         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10874         {
10875                 GL_DepthFunc(GL_LEQUAL);
10876                 GL_AlphaTest(false);
10877         }
10878 }
10879
10880 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10881 {
10882         int vi;
10883         int j;
10884         r_vertexgeneric_t *batchvertex;
10885         float c[4];
10886
10887 //      R_Mesh_ResetTextureState();
10888         R_SetupShader_Generic_NoTexture(false, false);
10889
10890         if(rsurface.texture && rsurface.texture->currentskinframe)
10891         {
10892                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10893                 c[3] *= rsurface.texture->currentalpha;
10894         }
10895         else
10896         {
10897                 c[0] = 1;
10898                 c[1] = 0;
10899                 c[2] = 1;
10900                 c[3] = 1;
10901         }
10902
10903         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10904         {
10905                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10906                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10907                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10908         }
10909
10910         // brighten it up (as texture value 127 means "unlit")
10911         c[0] *= 2 * r_refdef.view.colorscale;
10912         c[1] *= 2 * r_refdef.view.colorscale;
10913         c[2] *= 2 * r_refdef.view.colorscale;
10914
10915         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10916                 c[3] *= r_wateralpha.value;
10917
10918         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10919         {
10920                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10921                 GL_DepthMask(false);
10922         }
10923         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10924         {
10925                 GL_BlendFunc(GL_ONE, GL_ONE);
10926                 GL_DepthMask(false);
10927         }
10928         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10929         {
10930                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10931                 GL_DepthMask(false);
10932         }
10933         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10934         {
10935                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10936                 GL_DepthMask(false);
10937         }
10938         else
10939         {
10940                 GL_BlendFunc(GL_ONE, GL_ZERO);
10941                 GL_DepthMask(writedepth);
10942         }
10943
10944         if (r_showsurfaces.integer == 3)
10945         {
10946                 rsurface.passcolor4f = NULL;
10947
10948                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10949                 {
10950                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10951
10952                         rsurface.passcolor4f = NULL;
10953                         rsurface.passcolor4f_vertexbuffer = 0;
10954                         rsurface.passcolor4f_bufferoffset = 0;
10955                 }
10956                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10957                 {
10958                         qboolean applycolor = true;
10959                         float one = 1.0;
10960
10961                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10962
10963                         r_refdef.lightmapintensity = 1;
10964                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10965                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10966                 }
10967                 else if (FAKELIGHT_ENABLED)
10968                 {
10969                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10970
10971                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10972                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10973                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10974                 }
10975                 else
10976                 {
10977                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10978
10979                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10980                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10981                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10982                 }
10983
10984                 if(!rsurface.passcolor4f)
10985                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10986
10987                 RSurf_DrawBatch_GL11_ApplyAmbient();
10988                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10989                 if(r_refdef.fogenabled)
10990                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10991                 RSurf_DrawBatch_GL11_ClampColor();
10992
10993                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10994                 R_SetupShader_Generic_NoTexture(false, false);
10995                 RSurf_DrawBatch();
10996         }
10997         else if (!r_refdef.view.showdebug)
10998         {
10999                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11000                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11001                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11002                 {
11003                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11004                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11005                 }
11006                 R_Mesh_PrepareVertices_Generic_Unlock();
11007                 RSurf_DrawBatch();
11008         }
11009         else if (r_showsurfaces.integer == 4)
11010         {
11011                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11012                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11013                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11014                 {
11015                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11016                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11017                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11018                 }
11019                 R_Mesh_PrepareVertices_Generic_Unlock();
11020                 RSurf_DrawBatch();
11021         }
11022         else if (r_showsurfaces.integer == 2)
11023         {
11024                 const int *e;
11025                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11026                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11027                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11028                 {
11029                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11030                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11031                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11032                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11033                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11034                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11035                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11036                 }
11037                 R_Mesh_PrepareVertices_Generic_Unlock();
11038                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11039         }
11040         else
11041         {
11042                 int texturesurfaceindex;
11043                 int k;
11044                 const msurface_t *surface;
11045                 float surfacecolor4f[4];
11046                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11047                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11048                 vi = 0;
11049                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11050                 {
11051                         surface = texturesurfacelist[texturesurfaceindex];
11052                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11053                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11054                         for (j = 0;j < surface->num_vertices;j++)
11055                         {
11056                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11057                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11058                                 vi++;
11059                         }
11060                 }
11061                 R_Mesh_PrepareVertices_Generic_Unlock();
11062                 RSurf_DrawBatch();
11063         }
11064 }
11065
11066 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11067 {
11068         CHECKGLERROR
11069         RSurf_SetupDepthAndCulling();
11070         if (r_showsurfaces.integer)
11071         {
11072                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11073                 return;
11074         }
11075         switch (vid.renderpath)
11076         {
11077         case RENDERPATH_GL20:
11078         case RENDERPATH_D3D9:
11079         case RENDERPATH_D3D10:
11080         case RENDERPATH_D3D11:
11081         case RENDERPATH_SOFT:
11082         case RENDERPATH_GLES2:
11083                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11084                 break;
11085         case RENDERPATH_GL13:
11086         case RENDERPATH_GLES1:
11087                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11088                 break;
11089         case RENDERPATH_GL11:
11090                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11091                 break;
11092         }
11093         CHECKGLERROR
11094 }
11095
11096 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11097 {
11098         CHECKGLERROR
11099         RSurf_SetupDepthAndCulling();
11100         if (r_showsurfaces.integer)
11101         {
11102                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11103                 return;
11104         }
11105         switch (vid.renderpath)
11106         {
11107         case RENDERPATH_GL20:
11108         case RENDERPATH_D3D9:
11109         case RENDERPATH_D3D10:
11110         case RENDERPATH_D3D11:
11111         case RENDERPATH_SOFT:
11112         case RENDERPATH_GLES2:
11113                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11114                 break;
11115         case RENDERPATH_GL13:
11116         case RENDERPATH_GLES1:
11117                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11118                 break;
11119         case RENDERPATH_GL11:
11120                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11121                 break;
11122         }
11123         CHECKGLERROR
11124 }
11125
11126 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11127 {
11128         int i, j;
11129         int texturenumsurfaces, endsurface;
11130         texture_t *texture;
11131         const msurface_t *surface;
11132         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11133
11134         // if the model is static it doesn't matter what value we give for
11135         // wantnormals and wanttangents, so this logic uses only rules applicable
11136         // to a model, knowing that they are meaningless otherwise
11137         if (ent == r_refdef.scene.worldentity)
11138                 RSurf_ActiveWorldEntity();
11139         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11140                 RSurf_ActiveModelEntity(ent, false, false, false);
11141         else
11142         {
11143                 switch (vid.renderpath)
11144                 {
11145                 case RENDERPATH_GL20:
11146                 case RENDERPATH_D3D9:
11147                 case RENDERPATH_D3D10:
11148                 case RENDERPATH_D3D11:
11149                 case RENDERPATH_SOFT:
11150                 case RENDERPATH_GLES2:
11151                         RSurf_ActiveModelEntity(ent, true, true, false);
11152                         break;
11153                 case RENDERPATH_GL11:
11154                 case RENDERPATH_GL13:
11155                 case RENDERPATH_GLES1:
11156                         RSurf_ActiveModelEntity(ent, true, false, false);
11157                         break;
11158                 }
11159         }
11160
11161         if (r_transparentdepthmasking.integer)
11162         {
11163                 qboolean setup = false;
11164                 for (i = 0;i < numsurfaces;i = j)
11165                 {
11166                         j = i + 1;
11167                         surface = rsurface.modelsurfaces + surfacelist[i];
11168                         texture = surface->texture;
11169                         rsurface.texture = R_GetCurrentTexture(texture);
11170                         rsurface.lightmaptexture = NULL;
11171                         rsurface.deluxemaptexture = NULL;
11172                         rsurface.uselightmaptexture = false;
11173                         // scan ahead until we find a different texture
11174                         endsurface = min(i + 1024, numsurfaces);
11175                         texturenumsurfaces = 0;
11176                         texturesurfacelist[texturenumsurfaces++] = surface;
11177                         for (;j < endsurface;j++)
11178                         {
11179                                 surface = rsurface.modelsurfaces + surfacelist[j];
11180                                 if (texture != surface->texture)
11181                                         break;
11182                                 texturesurfacelist[texturenumsurfaces++] = surface;
11183                         }
11184                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11185                                 continue;
11186                         // render the range of surfaces as depth
11187                         if (!setup)
11188                         {
11189                                 setup = true;
11190                                 GL_ColorMask(0,0,0,0);
11191                                 GL_Color(1,1,1,1);
11192                                 GL_DepthTest(true);
11193                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11194                                 GL_DepthMask(true);
11195 //                              R_Mesh_ResetTextureState();
11196                         }
11197                         RSurf_SetupDepthAndCulling();
11198                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11199                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11200                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11201                         RSurf_DrawBatch();
11202                 }
11203                 if (setup)
11204                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11205         }
11206
11207         for (i = 0;i < numsurfaces;i = j)
11208         {
11209                 j = i + 1;
11210                 surface = rsurface.modelsurfaces + surfacelist[i];
11211                 texture = surface->texture;
11212                 rsurface.texture = R_GetCurrentTexture(texture);
11213                 // scan ahead until we find a different texture
11214                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11215                 texturenumsurfaces = 0;
11216                 texturesurfacelist[texturenumsurfaces++] = surface;
11217                 if(FAKELIGHT_ENABLED)
11218                 {
11219                         rsurface.lightmaptexture = NULL;
11220                         rsurface.deluxemaptexture = NULL;
11221                         rsurface.uselightmaptexture = false;
11222                         for (;j < endsurface;j++)
11223                         {
11224                                 surface = rsurface.modelsurfaces + surfacelist[j];
11225                                 if (texture != surface->texture)
11226                                         break;
11227                                 texturesurfacelist[texturenumsurfaces++] = surface;
11228                         }
11229                 }
11230                 else
11231                 {
11232                         rsurface.lightmaptexture = surface->lightmaptexture;
11233                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11234                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11235                         for (;j < endsurface;j++)
11236                         {
11237                                 surface = rsurface.modelsurfaces + surfacelist[j];
11238                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11239                                         break;
11240                                 texturesurfacelist[texturenumsurfaces++] = surface;
11241                         }
11242                 }
11243                 // render the range of surfaces
11244                 if (ent == r_refdef.scene.worldentity)
11245                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11246                 else
11247                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11248         }
11249         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11250 }
11251
11252 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11253 {
11254         // transparent surfaces get pushed off into the transparent queue
11255         int surfacelistindex;
11256         const msurface_t *surface;
11257         vec3_t tempcenter, center;
11258         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11259         {
11260                 surface = texturesurfacelist[surfacelistindex];
11261                 if (r_transparent_sortsurfacesbynearest.integer)
11262                 {
11263                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11264                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11265                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11266                 }
11267                 else
11268                 {
11269                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11270                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11271                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11272                 }
11273                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11274                 if (rsurface.entity->transparent_offset) // transparent offset
11275                 {
11276                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11277                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11278                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11279                 }
11280                 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);
11281         }
11282 }
11283
11284 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11285 {
11286         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11287                 return;
11288         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11289                 return;
11290         RSurf_SetupDepthAndCulling();
11291         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11292         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11293         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11294         RSurf_DrawBatch();
11295 }
11296
11297 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11298 {
11299         CHECKGLERROR
11300         if (depthonly)
11301                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11302         else if (prepass)
11303         {
11304                 if (!rsurface.texture->currentnumlayers)
11305                         return;
11306                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11307                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11308                 else
11309                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11310         }
11311         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11312                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11313         else if (!rsurface.texture->currentnumlayers)
11314                 return;
11315         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11316         {
11317                 // in the deferred case, transparent surfaces were queued during prepass
11318                 if (!r_shadow_usingdeferredprepass)
11319                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11320         }
11321         else
11322         {
11323                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11324                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11325         }
11326         CHECKGLERROR
11327 }
11328
11329 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11330 {
11331         int i, j;
11332         texture_t *texture;
11333         R_FrameData_SetMark();
11334         // break the surface list down into batches by texture and use of lightmapping
11335         for (i = 0;i < numsurfaces;i = j)
11336         {
11337                 j = i + 1;
11338                 // texture is the base texture pointer, rsurface.texture is the
11339                 // current frame/skin the texture is directing us to use (for example
11340                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11341                 // use skin 1 instead)
11342                 texture = surfacelist[i]->texture;
11343                 rsurface.texture = R_GetCurrentTexture(texture);
11344                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11345                 {
11346                         // if this texture is not the kind we want, skip ahead to the next one
11347                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11348                                 ;
11349                         continue;
11350                 }
11351                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11352                 {
11353                         rsurface.lightmaptexture = NULL;
11354                         rsurface.deluxemaptexture = NULL;
11355                         rsurface.uselightmaptexture = false;
11356                         // simply scan ahead until we find a different texture or lightmap state
11357                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11358                                 ;
11359                 }
11360                 else
11361                 {
11362                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11363                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11364                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11365                         // simply scan ahead until we find a different texture or lightmap state
11366                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11367                                 ;
11368                 }
11369                 // render the range of surfaces
11370                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11371         }
11372         R_FrameData_ReturnToMark();
11373 }
11374
11375 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11376 {
11377         CHECKGLERROR
11378         if (depthonly)
11379                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11380         else if (prepass)
11381         {
11382                 if (!rsurface.texture->currentnumlayers)
11383                         return;
11384                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11385                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11386                 else
11387                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11388         }
11389         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11390                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11391         else if (!rsurface.texture->currentnumlayers)
11392                 return;
11393         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11394         {
11395                 // in the deferred case, transparent surfaces were queued during prepass
11396                 if (!r_shadow_usingdeferredprepass)
11397                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11398         }
11399         else
11400         {
11401                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11402                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11403         }
11404         CHECKGLERROR
11405 }
11406
11407 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11408 {
11409         int i, j;
11410         texture_t *texture;
11411         R_FrameData_SetMark();
11412         // break the surface list down into batches by texture and use of lightmapping
11413         for (i = 0;i < numsurfaces;i = j)
11414         {
11415                 j = i + 1;
11416                 // texture is the base texture pointer, rsurface.texture is the
11417                 // current frame/skin the texture is directing us to use (for example
11418                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11419                 // use skin 1 instead)
11420                 texture = surfacelist[i]->texture;
11421                 rsurface.texture = R_GetCurrentTexture(texture);
11422                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11423                 {
11424                         // if this texture is not the kind we want, skip ahead to the next one
11425                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11426                                 ;
11427                         continue;
11428                 }
11429                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11430                 {
11431                         rsurface.lightmaptexture = NULL;
11432                         rsurface.deluxemaptexture = NULL;
11433                         rsurface.uselightmaptexture = false;
11434                         // simply scan ahead until we find a different texture or lightmap state
11435                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11436                                 ;
11437                 }
11438                 else
11439                 {
11440                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11441                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11442                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11443                         // simply scan ahead until we find a different texture or lightmap state
11444                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11445                                 ;
11446                 }
11447                 // render the range of surfaces
11448                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11449         }
11450         R_FrameData_ReturnToMark();
11451 }
11452
11453 float locboxvertex3f[6*4*3] =
11454 {
11455         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11456         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11457         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11458         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11459         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11460         1,0,0, 0,0,0, 0,1,0, 1,1,0
11461 };
11462
11463 unsigned short locboxelements[6*2*3] =
11464 {
11465          0, 1, 2, 0, 2, 3,
11466          4, 5, 6, 4, 6, 7,
11467          8, 9,10, 8,10,11,
11468         12,13,14, 12,14,15,
11469         16,17,18, 16,18,19,
11470         20,21,22, 20,22,23
11471 };
11472
11473 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11474 {
11475         int i, j;
11476         cl_locnode_t *loc = (cl_locnode_t *)ent;
11477         vec3_t mins, size;
11478         float vertex3f[6*4*3];
11479         CHECKGLERROR
11480         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11481         GL_DepthMask(false);
11482         GL_DepthRange(0, 1);
11483         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11484         GL_DepthTest(true);
11485         GL_CullFace(GL_NONE);
11486         R_EntityMatrix(&identitymatrix);
11487
11488 //      R_Mesh_ResetTextureState();
11489
11490         i = surfacelist[0];
11491         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11492                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11493                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11494                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11495
11496         if (VectorCompare(loc->mins, loc->maxs))
11497         {
11498                 VectorSet(size, 2, 2, 2);
11499                 VectorMA(loc->mins, -0.5f, size, mins);
11500         }
11501         else
11502         {
11503                 VectorCopy(loc->mins, mins);
11504                 VectorSubtract(loc->maxs, loc->mins, size);
11505         }
11506
11507         for (i = 0;i < 6*4*3;)
11508                 for (j = 0;j < 3;j++, i++)
11509                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11510
11511         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11512         R_SetupShader_Generic_NoTexture(false, false);
11513         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11514 }
11515
11516 void R_DrawLocs(void)
11517 {
11518         int index;
11519         cl_locnode_t *loc, *nearestloc;
11520         vec3_t center;
11521         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11522         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11523         {
11524                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11525                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11526         }
11527 }
11528
11529 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11530 {
11531         if (decalsystem->decals)
11532                 Mem_Free(decalsystem->decals);
11533         memset(decalsystem, 0, sizeof(*decalsystem));
11534 }
11535
11536 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)
11537 {
11538         tridecal_t *decal;
11539         tridecal_t *decals;
11540         int i;
11541
11542         // expand or initialize the system
11543         if (decalsystem->maxdecals <= decalsystem->numdecals)
11544         {
11545                 decalsystem_t old = *decalsystem;
11546                 qboolean useshortelements;
11547                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11548                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11549                 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)));
11550                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11551                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11552                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11553                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11554                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11555                 if (decalsystem->numdecals)
11556                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11557                 if (old.decals)
11558                         Mem_Free(old.decals);
11559                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11560                         decalsystem->element3i[i] = i;
11561                 if (useshortelements)
11562                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11563                                 decalsystem->element3s[i] = i;
11564         }
11565
11566         // grab a decal and search for another free slot for the next one
11567         decals = decalsystem->decals;
11568         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11569         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11570                 ;
11571         decalsystem->freedecal = i;
11572         if (decalsystem->numdecals <= i)
11573                 decalsystem->numdecals = i + 1;
11574
11575         // initialize the decal
11576         decal->lived = 0;
11577         decal->triangleindex = triangleindex;
11578         decal->surfaceindex = surfaceindex;
11579         decal->decalsequence = decalsequence;
11580         decal->color4f[0][0] = c0[0];
11581         decal->color4f[0][1] = c0[1];
11582         decal->color4f[0][2] = c0[2];
11583         decal->color4f[0][3] = 1;
11584         decal->color4f[1][0] = c1[0];
11585         decal->color4f[1][1] = c1[1];
11586         decal->color4f[1][2] = c1[2];
11587         decal->color4f[1][3] = 1;
11588         decal->color4f[2][0] = c2[0];
11589         decal->color4f[2][1] = c2[1];
11590         decal->color4f[2][2] = c2[2];
11591         decal->color4f[2][3] = 1;
11592         decal->vertex3f[0][0] = v0[0];
11593         decal->vertex3f[0][1] = v0[1];
11594         decal->vertex3f[0][2] = v0[2];
11595         decal->vertex3f[1][0] = v1[0];
11596         decal->vertex3f[1][1] = v1[1];
11597         decal->vertex3f[1][2] = v1[2];
11598         decal->vertex3f[2][0] = v2[0];
11599         decal->vertex3f[2][1] = v2[1];
11600         decal->vertex3f[2][2] = v2[2];
11601         decal->texcoord2f[0][0] = t0[0];
11602         decal->texcoord2f[0][1] = t0[1];
11603         decal->texcoord2f[1][0] = t1[0];
11604         decal->texcoord2f[1][1] = t1[1];
11605         decal->texcoord2f[2][0] = t2[0];
11606         decal->texcoord2f[2][1] = t2[1];
11607         TriangleNormal(v0, v1, v2, decal->plane);
11608         VectorNormalize(decal->plane);
11609         decal->plane[3] = DotProduct(v0, decal->plane);
11610 }
11611
11612 extern cvar_t cl_decals_bias;
11613 extern cvar_t cl_decals_models;
11614 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11615 // baseparms, parms, temps
11616 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)
11617 {
11618         int cornerindex;
11619         int index;
11620         float v[9][3];
11621         const float *vertex3f;
11622         const float *normal3f;
11623         int numpoints;
11624         float points[2][9][3];
11625         float temp[3];
11626         float tc[9][2];
11627         float f;
11628         float c[9][4];
11629         const int *e;
11630
11631         e = rsurface.modelelement3i + 3*triangleindex;
11632
11633         vertex3f = rsurface.modelvertex3f;
11634         normal3f = rsurface.modelnormal3f;
11635
11636         if (normal3f)
11637         {
11638                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11639                 {
11640                         index = 3*e[cornerindex];
11641                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11642                 }
11643         }
11644         else
11645         {
11646                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11647                 {
11648                         index = 3*e[cornerindex];
11649                         VectorCopy(vertex3f + index, v[cornerindex]);
11650                 }
11651         }
11652
11653         // cull backfaces
11654         //TriangleNormal(v[0], v[1], v[2], normal);
11655         //if (DotProduct(normal, localnormal) < 0.0f)
11656         //      continue;
11657         // clip by each of the box planes formed from the projection matrix
11658         // if anything survives, we emit the decal
11659         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]);
11660         if (numpoints < 3)
11661                 return;
11662         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]);
11663         if (numpoints < 3)
11664                 return;
11665         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]);
11666         if (numpoints < 3)
11667                 return;
11668         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]);
11669         if (numpoints < 3)
11670                 return;
11671         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]);
11672         if (numpoints < 3)
11673                 return;
11674         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]);
11675         if (numpoints < 3)
11676                 return;
11677         // some part of the triangle survived, so we have to accept it...
11678         if (dynamic)
11679         {
11680                 // dynamic always uses the original triangle
11681                 numpoints = 3;
11682                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11683                 {
11684                         index = 3*e[cornerindex];
11685                         VectorCopy(vertex3f + index, v[cornerindex]);
11686                 }
11687         }
11688         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11689         {
11690                 // convert vertex positions to texcoords
11691                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11692                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11693                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11694                 // calculate distance fade from the projection origin
11695                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11696                 f = bound(0.0f, f, 1.0f);
11697                 c[cornerindex][0] = r * f;
11698                 c[cornerindex][1] = g * f;
11699                 c[cornerindex][2] = b * f;
11700                 c[cornerindex][3] = 1.0f;
11701                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11702         }
11703         if (dynamic)
11704                 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);
11705         else
11706                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11707                         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);
11708 }
11709 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)
11710 {
11711         matrix4x4_t projection;
11712         decalsystem_t *decalsystem;
11713         qboolean dynamic;
11714         dp_model_t *model;
11715         const msurface_t *surface;
11716         const msurface_t *surfaces;
11717         const int *surfacelist;
11718         const texture_t *texture;
11719         int numtriangles;
11720         int numsurfacelist;
11721         int surfacelistindex;
11722         int surfaceindex;
11723         int triangleindex;
11724         float localorigin[3];
11725         float localnormal[3];
11726         float localmins[3];
11727         float localmaxs[3];
11728         float localsize;
11729         //float normal[3];
11730         float planes[6][4];
11731         float angles[3];
11732         bih_t *bih;
11733         int bih_triangles_count;
11734         int bih_triangles[256];
11735         int bih_surfaces[256];
11736
11737         decalsystem = &ent->decalsystem;
11738         model = ent->model;
11739         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11740         {
11741                 R_DecalSystem_Reset(&ent->decalsystem);
11742                 return;
11743         }
11744
11745         if (!model->brush.data_leafs && !cl_decals_models.integer)
11746         {
11747                 if (decalsystem->model)
11748                         R_DecalSystem_Reset(decalsystem);
11749                 return;
11750         }
11751
11752         if (decalsystem->model != model)
11753                 R_DecalSystem_Reset(decalsystem);
11754         decalsystem->model = model;
11755
11756         RSurf_ActiveModelEntity(ent, true, false, false);
11757
11758         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11759         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11760         VectorNormalize(localnormal);
11761         localsize = worldsize*rsurface.inversematrixscale;
11762         localmins[0] = localorigin[0] - localsize;
11763         localmins[1] = localorigin[1] - localsize;
11764         localmins[2] = localorigin[2] - localsize;
11765         localmaxs[0] = localorigin[0] + localsize;
11766         localmaxs[1] = localorigin[1] + localsize;
11767         localmaxs[2] = localorigin[2] + localsize;
11768
11769         //VectorCopy(localnormal, planes[4]);
11770         //VectorVectors(planes[4], planes[2], planes[0]);
11771         AnglesFromVectors(angles, localnormal, NULL, false);
11772         AngleVectors(angles, planes[0], planes[2], planes[4]);
11773         VectorNegate(planes[0], planes[1]);
11774         VectorNegate(planes[2], planes[3]);
11775         VectorNegate(planes[4], planes[5]);
11776         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11777         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11778         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11779         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11780         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11781         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11782
11783 #if 1
11784 // works
11785 {
11786         matrix4x4_t forwardprojection;
11787         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11788         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11789 }
11790 #else
11791 // broken
11792 {
11793         float projectionvector[4][3];
11794         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11795         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11796         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11797         projectionvector[0][0] = planes[0][0] * ilocalsize;
11798         projectionvector[0][1] = planes[1][0] * ilocalsize;
11799         projectionvector[0][2] = planes[2][0] * ilocalsize;
11800         projectionvector[1][0] = planes[0][1] * ilocalsize;
11801         projectionvector[1][1] = planes[1][1] * ilocalsize;
11802         projectionvector[1][2] = planes[2][1] * ilocalsize;
11803         projectionvector[2][0] = planes[0][2] * ilocalsize;
11804         projectionvector[2][1] = planes[1][2] * ilocalsize;
11805         projectionvector[2][2] = planes[2][2] * ilocalsize;
11806         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11807         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11808         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11809         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11810 }
11811 #endif
11812
11813         dynamic = model->surfmesh.isanimated;
11814         numsurfacelist = model->nummodelsurfaces;
11815         surfacelist = model->sortedmodelsurfaces;
11816         surfaces = model->data_surfaces;
11817
11818         bih = NULL;
11819         bih_triangles_count = -1;
11820         if(!dynamic)
11821         {
11822                 if(model->render_bih.numleafs)
11823                         bih = &model->render_bih;
11824                 else if(model->collision_bih.numleafs)
11825                         bih = &model->collision_bih;
11826         }
11827         if(bih)
11828                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11829         if(bih_triangles_count == 0)
11830                 return;
11831         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11832                 return;
11833         if(bih_triangles_count > 0)
11834         {
11835                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11836                 {
11837                         surfaceindex = bih_surfaces[triangleindex];
11838                         surface = surfaces + surfaceindex;
11839                         texture = surface->texture;
11840                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11841                                 continue;
11842                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11843                                 continue;
11844                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11845                 }
11846         }
11847         else
11848         {
11849                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11850                 {
11851                         surfaceindex = surfacelist[surfacelistindex];
11852                         surface = surfaces + surfaceindex;
11853                         // check cull box first because it rejects more than any other check
11854                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11855                                 continue;
11856                         // skip transparent surfaces
11857                         texture = surface->texture;
11858                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11859                                 continue;
11860                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11861                                 continue;
11862                         numtriangles = surface->num_triangles;
11863                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11864                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11865                 }
11866         }
11867 }
11868
11869 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11870 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)
11871 {
11872         int renderentityindex;
11873         float worldmins[3];
11874         float worldmaxs[3];
11875         entity_render_t *ent;
11876
11877         if (!cl_decals_newsystem.integer)
11878                 return;
11879
11880         worldmins[0] = worldorigin[0] - worldsize;
11881         worldmins[1] = worldorigin[1] - worldsize;
11882         worldmins[2] = worldorigin[2] - worldsize;
11883         worldmaxs[0] = worldorigin[0] + worldsize;
11884         worldmaxs[1] = worldorigin[1] + worldsize;
11885         worldmaxs[2] = worldorigin[2] + worldsize;
11886
11887         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11888
11889         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11890         {
11891                 ent = r_refdef.scene.entities[renderentityindex];
11892                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11893                         continue;
11894
11895                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11896         }
11897 }
11898
11899 typedef struct r_decalsystem_splatqueue_s
11900 {
11901         vec3_t worldorigin;
11902         vec3_t worldnormal;
11903         float color[4];
11904         float tcrange[4];
11905         float worldsize;
11906         int decalsequence;
11907 }
11908 r_decalsystem_splatqueue_t;
11909
11910 int r_decalsystem_numqueued = 0;
11911 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11912
11913 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)
11914 {
11915         r_decalsystem_splatqueue_t *queue;
11916
11917         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11918                 return;
11919
11920         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11921         VectorCopy(worldorigin, queue->worldorigin);
11922         VectorCopy(worldnormal, queue->worldnormal);
11923         Vector4Set(queue->color, r, g, b, a);
11924         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11925         queue->worldsize = worldsize;
11926         queue->decalsequence = cl.decalsequence++;
11927 }
11928
11929 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11930 {
11931         int i;
11932         r_decalsystem_splatqueue_t *queue;
11933
11934         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11935                 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);
11936         r_decalsystem_numqueued = 0;
11937 }
11938
11939 extern cvar_t cl_decals_max;
11940 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11941 {
11942         int i;
11943         decalsystem_t *decalsystem = &ent->decalsystem;
11944         int numdecals;
11945         int killsequence;
11946         tridecal_t *decal;
11947         float frametime;
11948         float lifetime;
11949
11950         if (!decalsystem->numdecals)
11951                 return;
11952
11953         if (r_showsurfaces.integer)
11954                 return;
11955
11956         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11957         {
11958                 R_DecalSystem_Reset(decalsystem);
11959                 return;
11960         }
11961
11962         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11963         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11964
11965         if (decalsystem->lastupdatetime)
11966                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11967         else
11968                 frametime = 0;
11969         decalsystem->lastupdatetime = r_refdef.scene.time;
11970         numdecals = decalsystem->numdecals;
11971
11972         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11973         {
11974                 if (decal->color4f[0][3])
11975                 {
11976                         decal->lived += frametime;
11977                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11978                         {
11979                                 memset(decal, 0, sizeof(*decal));
11980                                 if (decalsystem->freedecal > i)
11981                                         decalsystem->freedecal = i;
11982                         }
11983                 }
11984         }
11985         decal = decalsystem->decals;
11986         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11987                 numdecals--;
11988
11989         // collapse the array by shuffling the tail decals into the gaps
11990         for (;;)
11991         {
11992                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11993                         decalsystem->freedecal++;
11994                 if (decalsystem->freedecal == numdecals)
11995                         break;
11996                 decal[decalsystem->freedecal] = decal[--numdecals];
11997         }
11998
11999         decalsystem->numdecals = numdecals;
12000
12001         if (numdecals <= 0)
12002         {
12003                 // if there are no decals left, reset decalsystem
12004                 R_DecalSystem_Reset(decalsystem);
12005         }
12006 }
12007
12008 extern skinframe_t *decalskinframe;
12009 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12010 {
12011         int i;
12012         decalsystem_t *decalsystem = &ent->decalsystem;
12013         int numdecals;
12014         tridecal_t *decal;
12015         float faderate;
12016         float alpha;
12017         float *v3f;
12018         float *c4f;
12019         float *t2f;
12020         const int *e;
12021         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12022         int numtris = 0;
12023
12024         numdecals = decalsystem->numdecals;
12025         if (!numdecals)
12026                 return;
12027
12028         if (r_showsurfaces.integer)
12029                 return;
12030
12031         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12032         {
12033                 R_DecalSystem_Reset(decalsystem);
12034                 return;
12035         }
12036
12037         // if the model is static it doesn't matter what value we give for
12038         // wantnormals and wanttangents, so this logic uses only rules applicable
12039         // to a model, knowing that they are meaningless otherwise
12040         if (ent == r_refdef.scene.worldentity)
12041                 RSurf_ActiveWorldEntity();
12042         else
12043                 RSurf_ActiveModelEntity(ent, false, false, false);
12044
12045         decalsystem->lastupdatetime = r_refdef.scene.time;
12046
12047         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12048
12049         // update vertex positions for animated models
12050         v3f = decalsystem->vertex3f;
12051         c4f = decalsystem->color4f;
12052         t2f = decalsystem->texcoord2f;
12053         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12054         {
12055                 if (!decal->color4f[0][3])
12056                         continue;
12057
12058                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12059                         continue;
12060
12061                 // skip backfaces
12062                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12063                         continue;
12064
12065                 // update color values for fading decals
12066                 if (decal->lived >= cl_decals_time.value)
12067                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12068                 else
12069                         alpha = 1.0f;
12070
12071                 c4f[ 0] = decal->color4f[0][0] * alpha;
12072                 c4f[ 1] = decal->color4f[0][1] * alpha;
12073                 c4f[ 2] = decal->color4f[0][2] * alpha;
12074                 c4f[ 3] = 1;
12075                 c4f[ 4] = decal->color4f[1][0] * alpha;
12076                 c4f[ 5] = decal->color4f[1][1] * alpha;
12077                 c4f[ 6] = decal->color4f[1][2] * alpha;
12078                 c4f[ 7] = 1;
12079                 c4f[ 8] = decal->color4f[2][0] * alpha;
12080                 c4f[ 9] = decal->color4f[2][1] * alpha;
12081                 c4f[10] = decal->color4f[2][2] * alpha;
12082                 c4f[11] = 1;
12083
12084                 t2f[0] = decal->texcoord2f[0][0];
12085                 t2f[1] = decal->texcoord2f[0][1];
12086                 t2f[2] = decal->texcoord2f[1][0];
12087                 t2f[3] = decal->texcoord2f[1][1];
12088                 t2f[4] = decal->texcoord2f[2][0];
12089                 t2f[5] = decal->texcoord2f[2][1];
12090
12091                 // update vertex positions for animated models
12092                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12093                 {
12094                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12095                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12096                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12097                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12098                 }
12099                 else
12100                 {
12101                         VectorCopy(decal->vertex3f[0], v3f);
12102                         VectorCopy(decal->vertex3f[1], v3f + 3);
12103                         VectorCopy(decal->vertex3f[2], v3f + 6);
12104                 }
12105
12106                 if (r_refdef.fogenabled)
12107                 {
12108                         alpha = RSurf_FogVertex(v3f);
12109                         VectorScale(c4f, alpha, c4f);
12110                         alpha = RSurf_FogVertex(v3f + 3);
12111                         VectorScale(c4f + 4, alpha, c4f + 4);
12112                         alpha = RSurf_FogVertex(v3f + 6);
12113                         VectorScale(c4f + 8, alpha, c4f + 8);
12114                 }
12115
12116                 v3f += 9;
12117                 c4f += 12;
12118                 t2f += 6;
12119                 numtris++;
12120         }
12121
12122         if (numtris > 0)
12123         {
12124                 r_refdef.stats[r_stat_drawndecals] += numtris;
12125
12126                 // now render the decals all at once
12127                 // (this assumes they all use one particle font texture!)
12128                 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);
12129 //              R_Mesh_ResetTextureState();
12130                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12131                 GL_DepthMask(false);
12132                 GL_DepthRange(0, 1);
12133                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12134                 GL_DepthTest(true);
12135                 GL_CullFace(GL_NONE);
12136                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12137                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12138                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12139         }
12140 }
12141
12142 static void R_DrawModelDecals(void)
12143 {
12144         int i, numdecals;
12145
12146         // fade faster when there are too many decals
12147         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12148         for (i = 0;i < r_refdef.scene.numentities;i++)
12149                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12150
12151         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12152         for (i = 0;i < r_refdef.scene.numentities;i++)
12153                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12154                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12155
12156         R_DecalSystem_ApplySplatEntitiesQueue();
12157
12158         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12159         for (i = 0;i < r_refdef.scene.numentities;i++)
12160                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12161
12162         r_refdef.stats[r_stat_totaldecals] += numdecals;
12163
12164         if (r_showsurfaces.integer)
12165                 return;
12166
12167         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12168
12169         for (i = 0;i < r_refdef.scene.numentities;i++)
12170         {
12171                 if (!r_refdef.viewcache.entityvisible[i])
12172                         continue;
12173                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12174                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12175         }
12176 }
12177
12178 extern cvar_t mod_collision_bih;
12179 static void R_DrawDebugModel(void)
12180 {
12181         entity_render_t *ent = rsurface.entity;
12182         int i, j, k, l, flagsmask;
12183         const msurface_t *surface;
12184         dp_model_t *model = ent->model;
12185         vec3_t v;
12186
12187         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12188                 return;
12189
12190         if (r_showoverdraw.value > 0)
12191         {
12192                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12193                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12194                 R_SetupShader_Generic_NoTexture(false, false);
12195                 GL_DepthTest(false);
12196                 GL_DepthMask(false);
12197                 GL_DepthRange(0, 1);
12198                 GL_BlendFunc(GL_ONE, GL_ONE);
12199                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12200                 {
12201                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12202                                 continue;
12203                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12204                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12205                         {
12206                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12207                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12208                                 if (!rsurface.texture->currentlayers->depthmask)
12209                                         GL_Color(c, 0, 0, 1.0f);
12210                                 else if (ent == r_refdef.scene.worldentity)
12211                                         GL_Color(c, c, c, 1.0f);
12212                                 else
12213                                         GL_Color(0, c, 0, 1.0f);
12214                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12215                                 RSurf_DrawBatch();
12216                         }
12217                 }
12218                 rsurface.texture = NULL;
12219         }
12220
12221         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12222
12223 //      R_Mesh_ResetTextureState();
12224         R_SetupShader_Generic_NoTexture(false, false);
12225         GL_DepthRange(0, 1);
12226         GL_DepthTest(!r_showdisabledepthtest.integer);
12227         GL_DepthMask(false);
12228         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12229
12230         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12231         {
12232                 int triangleindex;
12233                 int bihleafindex;
12234                 qboolean cullbox = false;
12235                 const q3mbrush_t *brush;
12236                 const bih_t *bih = &model->collision_bih;
12237                 const bih_leaf_t *bihleaf;
12238                 float vertex3f[3][3];
12239                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12240                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12241                 {
12242                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12243                                 continue;
12244                         switch (bihleaf->type)
12245                         {
12246                         case BIH_BRUSH:
12247                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12248                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12249                                 {
12250                                         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);
12251                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12252                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12253                                 }
12254                                 break;
12255                         case BIH_COLLISIONTRIANGLE:
12256                                 triangleindex = bihleaf->itemindex;
12257                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12258                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12259                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12260                                 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);
12261                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12262                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12263                                 break;
12264                         case BIH_RENDERTRIANGLE:
12265                                 triangleindex = bihleaf->itemindex;
12266                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12267                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12268                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12269                                 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);
12270                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12271                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12272                                 break;
12273                         }
12274                 }
12275         }
12276
12277         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12278
12279 #ifndef USE_GLES2
12280         if (r_showtris.integer && qglPolygonMode)
12281         {
12282                 if (r_showdisabledepthtest.integer)
12283                 {
12284                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12285                         GL_DepthMask(false);
12286                 }
12287                 else
12288                 {
12289                         GL_BlendFunc(GL_ONE, GL_ZERO);
12290                         GL_DepthMask(true);
12291                 }
12292                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12293                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12294                 {
12295                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12296                                 continue;
12297                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12298                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12299                         {
12300                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12301                                 if (!rsurface.texture->currentlayers->depthmask)
12302                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12303                                 else if (ent == r_refdef.scene.worldentity)
12304                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12305                                 else
12306                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12307                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12308                                 RSurf_DrawBatch();
12309                         }
12310                 }
12311                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12312                 rsurface.texture = NULL;
12313         }
12314
12315         if (r_shownormals.value != 0 && qglBegin)
12316         {
12317                 if (r_showdisabledepthtest.integer)
12318                 {
12319                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12320                         GL_DepthMask(false);
12321                 }
12322                 else
12323                 {
12324                         GL_BlendFunc(GL_ONE, GL_ZERO);
12325                         GL_DepthMask(true);
12326                 }
12327                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12328                 {
12329                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12330                                 continue;
12331                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12332                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12333                         {
12334                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12335                                 qglBegin(GL_LINES);
12336                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12337                                 {
12338                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12339                                         {
12340                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12341                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12342                                                 qglVertex3f(v[0], v[1], v[2]);
12343                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12344                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12345                                                 qglVertex3f(v[0], v[1], v[2]);
12346                                         }
12347                                 }
12348                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12349                                 {
12350                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12351                                         {
12352                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12353                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12354                                                 qglVertex3f(v[0], v[1], v[2]);
12355                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12356                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12357                                                 qglVertex3f(v[0], v[1], v[2]);
12358                                         }
12359                                 }
12360                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12361                                 {
12362                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12363                                         {
12364                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12365                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12366                                                 qglVertex3f(v[0], v[1], v[2]);
12367                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12368                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12369                                                 qglVertex3f(v[0], v[1], v[2]);
12370                                         }
12371                                 }
12372                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12373                                 {
12374                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12375                                         {
12376                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12377                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12378                                                 qglVertex3f(v[0], v[1], v[2]);
12379                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12380                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12381                                                 qglVertex3f(v[0], v[1], v[2]);
12382                                         }
12383                                 }
12384                                 qglEnd();
12385                                 CHECKGLERROR
12386                         }
12387                 }
12388                 rsurface.texture = NULL;
12389         }
12390 #endif
12391 }
12392
12393 int r_maxsurfacelist = 0;
12394 const msurface_t **r_surfacelist = NULL;
12395 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12396 {
12397         int i, j, endj, flagsmask;
12398         dp_model_t *model = r_refdef.scene.worldmodel;
12399         msurface_t *surfaces;
12400         unsigned char *update;
12401         int numsurfacelist = 0;
12402         if (model == NULL)
12403                 return;
12404
12405         if (r_maxsurfacelist < model->num_surfaces)
12406         {
12407                 r_maxsurfacelist = model->num_surfaces;
12408                 if (r_surfacelist)
12409                         Mem_Free((msurface_t**)r_surfacelist);
12410                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12411         }
12412
12413         RSurf_ActiveWorldEntity();
12414
12415         surfaces = model->data_surfaces;
12416         update = model->brushq1.lightmapupdateflags;
12417
12418         // update light styles on this submodel
12419         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12420         {
12421                 model_brush_lightstyleinfo_t *style;
12422                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12423                 {
12424                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12425                         {
12426                                 int *list = style->surfacelist;
12427                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12428                                 for (j = 0;j < style->numsurfaces;j++)
12429                                         update[list[j]] = true;
12430                         }
12431                 }
12432         }
12433
12434         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12435
12436         if (debug)
12437         {
12438                 R_DrawDebugModel();
12439                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12440                 return;
12441         }
12442
12443         rsurface.lightmaptexture = NULL;
12444         rsurface.deluxemaptexture = NULL;
12445         rsurface.uselightmaptexture = false;
12446         rsurface.texture = NULL;
12447         rsurface.rtlight = NULL;
12448         numsurfacelist = 0;
12449         // add visible surfaces to draw list
12450         for (i = 0;i < model->nummodelsurfaces;i++)
12451         {
12452                 j = model->sortedmodelsurfaces[i];
12453                 if (r_refdef.viewcache.world_surfacevisible[j])
12454                         r_surfacelist[numsurfacelist++] = surfaces + j;
12455         }
12456         // update lightmaps if needed
12457         if (model->brushq1.firstrender)
12458         {
12459                 model->brushq1.firstrender = false;
12460                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12461                         if (update[j])
12462                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12463         }
12464         else if (update)
12465         {
12466                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12467                         if (r_refdef.viewcache.world_surfacevisible[j])
12468                                 if (update[j])
12469                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12470         }
12471         // don't do anything if there were no surfaces
12472         if (!numsurfacelist)
12473         {
12474                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12475                 return;
12476         }
12477         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12478
12479         // add to stats if desired
12480         if (r_speeds.integer && !skysurfaces && !depthonly)
12481         {
12482                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12483                 for (j = 0;j < numsurfacelist;j++)
12484                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12485         }
12486
12487         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12488 }
12489
12490 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12491 {
12492         int i, j, endj, flagsmask;
12493         dp_model_t *model = ent->model;
12494         msurface_t *surfaces;
12495         unsigned char *update;
12496         int numsurfacelist = 0;
12497         if (model == NULL)
12498                 return;
12499
12500         if (r_maxsurfacelist < model->num_surfaces)
12501         {
12502                 r_maxsurfacelist = model->num_surfaces;
12503                 if (r_surfacelist)
12504                         Mem_Free((msurface_t **)r_surfacelist);
12505                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12506         }
12507
12508         // if the model is static it doesn't matter what value we give for
12509         // wantnormals and wanttangents, so this logic uses only rules applicable
12510         // to a model, knowing that they are meaningless otherwise
12511         if (ent == r_refdef.scene.worldentity)
12512                 RSurf_ActiveWorldEntity();
12513         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12514                 RSurf_ActiveModelEntity(ent, false, false, false);
12515         else if (prepass)
12516                 RSurf_ActiveModelEntity(ent, true, true, true);
12517         else if (depthonly)
12518         {
12519                 switch (vid.renderpath)
12520                 {
12521                 case RENDERPATH_GL20:
12522                 case RENDERPATH_D3D9:
12523                 case RENDERPATH_D3D10:
12524                 case RENDERPATH_D3D11:
12525                 case RENDERPATH_SOFT:
12526                 case RENDERPATH_GLES2:
12527                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12528                         break;
12529                 case RENDERPATH_GL11:
12530                 case RENDERPATH_GL13:
12531                 case RENDERPATH_GLES1:
12532                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12533                         break;
12534                 }
12535         }
12536         else
12537         {
12538                 switch (vid.renderpath)
12539                 {
12540                 case RENDERPATH_GL20:
12541                 case RENDERPATH_D3D9:
12542                 case RENDERPATH_D3D10:
12543                 case RENDERPATH_D3D11:
12544                 case RENDERPATH_SOFT:
12545                 case RENDERPATH_GLES2:
12546                         RSurf_ActiveModelEntity(ent, true, true, false);
12547                         break;
12548                 case RENDERPATH_GL11:
12549                 case RENDERPATH_GL13:
12550                 case RENDERPATH_GLES1:
12551                         RSurf_ActiveModelEntity(ent, true, false, false);
12552                         break;
12553                 }
12554         }
12555
12556         surfaces = model->data_surfaces;
12557         update = model->brushq1.lightmapupdateflags;
12558
12559         // update light styles
12560         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12561         {
12562                 model_brush_lightstyleinfo_t *style;
12563                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12564                 {
12565                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12566                         {
12567                                 int *list = style->surfacelist;
12568                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12569                                 for (j = 0;j < style->numsurfaces;j++)
12570                                         update[list[j]] = true;
12571                         }
12572                 }
12573         }
12574
12575         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12576
12577         if (debug)
12578         {
12579                 R_DrawDebugModel();
12580                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12581                 return;
12582         }
12583
12584         rsurface.lightmaptexture = NULL;
12585         rsurface.deluxemaptexture = NULL;
12586         rsurface.uselightmaptexture = false;
12587         rsurface.texture = NULL;
12588         rsurface.rtlight = NULL;
12589         numsurfacelist = 0;
12590         // add visible surfaces to draw list
12591         for (i = 0;i < model->nummodelsurfaces;i++)
12592                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12593         // don't do anything if there were no surfaces
12594         if (!numsurfacelist)
12595         {
12596                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12597                 return;
12598         }
12599         // update lightmaps if needed
12600         if (update)
12601         {
12602                 int updated = 0;
12603                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12604                 {
12605                         if (update[j])
12606                         {
12607                                 updated++;
12608                                 R_BuildLightMap(ent, surfaces + j);
12609                         }
12610                 }
12611         }
12612
12613         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12614
12615         // add to stats if desired
12616         if (r_speeds.integer && !skysurfaces && !depthonly)
12617         {
12618                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12619                 for (j = 0;j < numsurfacelist;j++)
12620                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12621         }
12622
12623         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12624 }
12625
12626 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12627 {
12628         static texture_t texture;
12629         static msurface_t surface;
12630         const msurface_t *surfacelist = &surface;
12631
12632         // fake enough texture and surface state to render this geometry
12633
12634         texture.update_lastrenderframe = -1; // regenerate this texture
12635         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12636         texture.currentskinframe = skinframe;
12637         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12638         texture.offsetmapping = OFFSETMAPPING_OFF;
12639         texture.offsetscale = 1;
12640         texture.specularscalemod = 1;
12641         texture.specularpowermod = 1;
12642         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12643         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12644         // JUST GREP FOR "specularscalemod = 1".
12645
12646         surface.texture = &texture;
12647         surface.num_triangles = numtriangles;
12648         surface.num_firsttriangle = firsttriangle;
12649         surface.num_vertices = numvertices;
12650         surface.num_firstvertex = firstvertex;
12651
12652         // now render it
12653         rsurface.texture = R_GetCurrentTexture(surface.texture);
12654         rsurface.lightmaptexture = NULL;
12655         rsurface.deluxemaptexture = NULL;
12656         rsurface.uselightmaptexture = false;
12657         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12658 }
12659
12660 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)
12661 {
12662         static msurface_t surface;
12663         const msurface_t *surfacelist = &surface;
12664
12665         // fake enough texture and surface state to render this geometry
12666         surface.texture = texture;
12667         surface.num_triangles = numtriangles;
12668         surface.num_firsttriangle = firsttriangle;
12669         surface.num_vertices = numvertices;
12670         surface.num_firstvertex = firstvertex;
12671
12672         // now render it
12673         rsurface.texture = R_GetCurrentTexture(surface.texture);
12674         rsurface.lightmaptexture = NULL;
12675         rsurface.deluxemaptexture = NULL;
12676         rsurface.uselightmaptexture = false;
12677         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12678 }