]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
changed r_refdef.stats struct to be an array indexed by r_stat_* enums
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
81 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
82 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
83 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
84 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
85 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
86 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
87 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
88 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
89 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
90 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
91 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
92 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
93 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
94 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
95 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
96 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
97 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
98 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
99 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
100 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
101 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
102 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
103 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
104 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
105 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
106 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
107
108 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
109 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
110 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
111
112 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
113 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
114 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
115 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
116 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
117 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
118 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
119 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
120 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
121 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
122 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
123 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
124 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
125 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
126 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
127 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
128 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
130 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
131 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
132 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
133 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
134 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
135 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
136 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
137 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
138
139 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
140 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
141 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
142 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
143 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
144 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
145 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
146 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
147
148 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
149 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
150
151 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
152 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
153 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
154
155 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
156 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
157 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
158 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
159 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
160 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
161 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
162 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
163 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
164
165 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
166 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
167 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
168 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
169 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
170 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
171 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
172 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
173 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
174 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
175 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
176 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
177 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
178 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
179 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
180 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
181 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
182 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
183 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
184
185 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
186 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
187 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
188 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
189 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
190 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
191 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
192 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
193 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
194
195 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
196 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
197 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
198 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
199
200 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
201 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
202
203 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
204 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
205 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
206 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
207 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
208 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
209
210 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
211 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
212 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
213 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
214 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
215 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
217 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
218 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
219 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
220
221 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
222
223 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
224
225 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
226
227 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
228
229 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
230 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
231 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
232
233 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
234 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
235
236 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
237
238 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
239
240 extern cvar_t v_glslgamma;
241 extern cvar_t v_glslgamma_2d;
242
243 extern qboolean v_flipped_state;
244
245 r_framebufferstate_t r_fb;
246
247 /// shadow volume bsp struct with automatically growing nodes buffer
248 svbsp_t r_svbsp;
249
250 rtexture_t *r_texture_blanknormalmap;
251 rtexture_t *r_texture_white;
252 rtexture_t *r_texture_grey128;
253 rtexture_t *r_texture_black;
254 rtexture_t *r_texture_notexture;
255 rtexture_t *r_texture_whitecube;
256 rtexture_t *r_texture_normalizationcube;
257 rtexture_t *r_texture_fogattenuation;
258 rtexture_t *r_texture_fogheighttexture;
259 rtexture_t *r_texture_gammaramps;
260 unsigned int r_texture_gammaramps_serial;
261 //rtexture_t *r_texture_fogintensity;
262 rtexture_t *r_texture_reflectcube;
263
264 // TODO: hash lookups?
265 typedef struct cubemapinfo_s
266 {
267         char basename[64];
268         rtexture_t *texture;
269 }
270 cubemapinfo_t;
271
272 int r_texture_numcubemaps;
273 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
274
275 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
276 unsigned int r_numqueries;
277 unsigned int r_maxqueries;
278
279 typedef struct r_qwskincache_s
280 {
281         char name[MAX_QPATH];
282         skinframe_t *skinframe;
283 }
284 r_qwskincache_t;
285
286 static r_qwskincache_t *r_qwskincache;
287 static int r_qwskincache_size;
288
289 /// vertex coordinates for a quad that covers the screen exactly
290 extern const float r_screenvertex3f[12];
291 extern const float r_d3dscreenvertex3f[12];
292 const float r_screenvertex3f[12] =
293 {
294         0, 0, 0,
295         1, 0, 0,
296         1, 1, 0,
297         0, 1, 0
298 };
299 const float r_d3dscreenvertex3f[12] =
300 {
301         0, 1, 0,
302         1, 1, 0,
303         1, 0, 0,
304         0, 0, 0
305 };
306
307 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
308 {
309         int i;
310         for (i = 0;i < verts;i++)
311         {
312                 out[0] = in[0] * r;
313                 out[1] = in[1] * g;
314                 out[2] = in[2] * b;
315                 out[3] = in[3];
316                 in += 4;
317                 out += 4;
318         }
319 }
320
321 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
322 {
323         int i;
324         for (i = 0;i < verts;i++)
325         {
326                 out[0] = r;
327                 out[1] = g;
328                 out[2] = b;
329                 out[3] = a;
330                 out += 4;
331         }
332 }
333
334 // FIXME: move this to client?
335 void FOG_clear(void)
336 {
337         if (gamemode == GAME_NEHAHRA)
338         {
339                 Cvar_Set("gl_fogenable", "0");
340                 Cvar_Set("gl_fogdensity", "0.2");
341                 Cvar_Set("gl_fogred", "0.3");
342                 Cvar_Set("gl_foggreen", "0.3");
343                 Cvar_Set("gl_fogblue", "0.3");
344         }
345         r_refdef.fog_density = 0;
346         r_refdef.fog_red = 0;
347         r_refdef.fog_green = 0;
348         r_refdef.fog_blue = 0;
349         r_refdef.fog_alpha = 1;
350         r_refdef.fog_start = 0;
351         r_refdef.fog_end = 16384;
352         r_refdef.fog_height = 1<<30;
353         r_refdef.fog_fadedepth = 128;
354         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
355 }
356
357 static void R_BuildBlankTextures(void)
358 {
359         unsigned char data[4];
360         data[2] = 128; // normal X
361         data[1] = 128; // normal Y
362         data[0] = 255; // normal Z
363         data[3] = 255; // height
364         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365         data[0] = 255;
366         data[1] = 255;
367         data[2] = 255;
368         data[3] = 255;
369         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370         data[0] = 128;
371         data[1] = 128;
372         data[2] = 128;
373         data[3] = 255;
374         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 0;
376         data[1] = 0;
377         data[2] = 0;
378         data[3] = 255;
379         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380 }
381
382 static void R_BuildNoTexture(void)
383 {
384         int x, y;
385         unsigned char pix[16][16][4];
386         // this makes a light grey/dark grey checkerboard texture
387         for (y = 0;y < 16;y++)
388         {
389                 for (x = 0;x < 16;x++)
390                 {
391                         if ((y < 8) ^ (x < 8))
392                         {
393                                 pix[y][x][0] = 128;
394                                 pix[y][x][1] = 128;
395                                 pix[y][x][2] = 128;
396                                 pix[y][x][3] = 255;
397                         }
398                         else
399                         {
400                                 pix[y][x][0] = 64;
401                                 pix[y][x][1] = 64;
402                                 pix[y][x][2] = 64;
403                                 pix[y][x][3] = 255;
404                         }
405                 }
406         }
407         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
408 }
409
410 static void R_BuildWhiteCube(void)
411 {
412         unsigned char data[6*1*1*4];
413         memset(data, 255, sizeof(data));
414         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
415 }
416
417 static void R_BuildNormalizationCube(void)
418 {
419         int x, y, side;
420         vec3_t v;
421         vec_t s, t, intensity;
422 #define NORMSIZE 64
423         unsigned char *data;
424         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
425         for (side = 0;side < 6;side++)
426         {
427                 for (y = 0;y < NORMSIZE;y++)
428                 {
429                         for (x = 0;x < NORMSIZE;x++)
430                         {
431                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
432                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
433                                 switch(side)
434                                 {
435                                 default:
436                                 case 0:
437                                         v[0] = 1;
438                                         v[1] = -t;
439                                         v[2] = -s;
440                                         break;
441                                 case 1:
442                                         v[0] = -1;
443                                         v[1] = -t;
444                                         v[2] = s;
445                                         break;
446                                 case 2:
447                                         v[0] = s;
448                                         v[1] = 1;
449                                         v[2] = t;
450                                         break;
451                                 case 3:
452                                         v[0] = s;
453                                         v[1] = -1;
454                                         v[2] = -t;
455                                         break;
456                                 case 4:
457                                         v[0] = s;
458                                         v[1] = -t;
459                                         v[2] = 1;
460                                         break;
461                                 case 5:
462                                         v[0] = -s;
463                                         v[1] = -t;
464                                         v[2] = -1;
465                                         break;
466                                 }
467                                 intensity = 127.0f / sqrt(DotProduct(v, v));
468                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
469                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
470                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
471                                 data[((side*64+y)*64+x)*4+3] = 255;
472                         }
473                 }
474         }
475         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
476         Mem_Free(data);
477 }
478
479 static void R_BuildFogTexture(void)
480 {
481         int x, b;
482 #define FOGWIDTH 256
483         unsigned char data1[FOGWIDTH][4];
484         //unsigned char data2[FOGWIDTH][4];
485         double d, r, alpha;
486
487         r_refdef.fogmasktable_start = r_refdef.fog_start;
488         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
489         r_refdef.fogmasktable_range = r_refdef.fogrange;
490         r_refdef.fogmasktable_density = r_refdef.fog_density;
491
492         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
493         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
494         {
495                 d = (x * r - r_refdef.fogmasktable_start);
496                 if(developer_extra.integer)
497                         Con_DPrintf("%f ", d);
498                 d = max(0, d);
499                 if (r_fog_exp2.integer)
500                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
501                 else
502                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
503                 if(developer_extra.integer)
504                         Con_DPrintf(" : %f ", alpha);
505                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
506                 if(developer_extra.integer)
507                         Con_DPrintf(" = %f\n", alpha);
508                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
509         }
510
511         for (x = 0;x < FOGWIDTH;x++)
512         {
513                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
514                 data1[x][0] = b;
515                 data1[x][1] = b;
516                 data1[x][2] = b;
517                 data1[x][3] = 255;
518                 //data2[x][0] = 255 - b;
519                 //data2[x][1] = 255 - b;
520                 //data2[x][2] = 255 - b;
521                 //data2[x][3] = 255;
522         }
523         if (r_texture_fogattenuation)
524         {
525                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
526                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
527         }
528         else
529         {
530                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
531                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
532         }
533 }
534
535 static void R_BuildFogHeightTexture(void)
536 {
537         unsigned char *inpixels;
538         int size;
539         int x;
540         int y;
541         int j;
542         float c[4];
543         float f;
544         inpixels = NULL;
545         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
546         if (r_refdef.fogheighttexturename[0])
547                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
548         if (!inpixels)
549         {
550                 r_refdef.fog_height_tablesize = 0;
551                 if (r_texture_fogheighttexture)
552                         R_FreeTexture(r_texture_fogheighttexture);
553                 r_texture_fogheighttexture = NULL;
554                 if (r_refdef.fog_height_table2d)
555                         Mem_Free(r_refdef.fog_height_table2d);
556                 r_refdef.fog_height_table2d = NULL;
557                 if (r_refdef.fog_height_table1d)
558                         Mem_Free(r_refdef.fog_height_table1d);
559                 r_refdef.fog_height_table1d = NULL;
560                 return;
561         }
562         size = image_width;
563         r_refdef.fog_height_tablesize = size;
564         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
565         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
566         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
567         Mem_Free(inpixels);
568         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
569         // average fog color table accounting for every fog layer between a point
570         // and the camera.  (Note: attenuation is handled separately!)
571         for (y = 0;y < size;y++)
572         {
573                 for (x = 0;x < size;x++)
574                 {
575                         Vector4Clear(c);
576                         f = 0;
577                         if (x < y)
578                         {
579                                 for (j = x;j <= y;j++)
580                                 {
581                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
582                                         f++;
583                                 }
584                         }
585                         else
586                         {
587                                 for (j = x;j >= y;j--)
588                                 {
589                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
590                                         f++;
591                                 }
592                         }
593                         f = 1.0f / f;
594                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
595                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
596                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
597                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
598                 }
599         }
600         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
601 }
602
603 //=======================================================================================================================================================
604
605 static const char *builtinshaderstrings[] =
606 {
607 #include "shader_glsl.h"
608 0
609 };
610
611 const char *builtinhlslshaderstrings[] =
612 {
613 #include "shader_hlsl.h"
614 0
615 };
616
617 char *glslshaderstring = NULL;
618 char *hlslshaderstring = NULL;
619
620 //=======================================================================================================================================================
621
622 typedef struct shaderpermutationinfo_s
623 {
624         const char *pretext;
625         const char *name;
626 }
627 shaderpermutationinfo_t;
628
629 typedef struct shadermodeinfo_s
630 {
631         const char *filename;
632         const char *pretext;
633         const char *name;
634 }
635 shadermodeinfo_t;
636
637 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
638 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
639 {
640         {"#define USEDIFFUSE\n", " diffuse"},
641         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
642         {"#define USEVIEWTINT\n", " viewtint"},
643         {"#define USECOLORMAPPING\n", " colormapping"},
644         {"#define USESATURATION\n", " saturation"},
645         {"#define USEFOGINSIDE\n", " foginside"},
646         {"#define USEFOGOUTSIDE\n", " fogoutside"},
647         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
648         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
649         {"#define USEGAMMARAMPS\n", " gammaramps"},
650         {"#define USECUBEFILTER\n", " cubefilter"},
651         {"#define USEGLOW\n", " glow"},
652         {"#define USEBLOOM\n", " bloom"},
653         {"#define USESPECULAR\n", " specular"},
654         {"#define USEPOSTPROCESSING\n", " postprocessing"},
655         {"#define USEREFLECTION\n", " reflection"},
656         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
657         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
658         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
659         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
660         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
661         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
662         {"#define USEALPHAKILL\n", " alphakill"},
663         {"#define USEREFLECTCUBE\n", " reflectcube"},
664         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
665         {"#define USEBOUNCEGRID\n", " bouncegrid"},
666         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
667         {"#define USETRIPPY\n", " trippy"},
668         {"#define USEDEPTHRGB\n", " depthrgb"},
669         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
670         {"#define USESKELETAL\n", " skeletal"}
671 };
672
673 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
674 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
675 {
676         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
677         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
678         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
679         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
680         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
681         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
682         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
683         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
684         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
685         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
686         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
687         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
688         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
689         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
690         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
691         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
692         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
693 };
694
695 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
696 {
697         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
698         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
699         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
700         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
701         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
702         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
703         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
704         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
705         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
706         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
707         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
708         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
709         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
710         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
711         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
712         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
713         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
714 };
715
716 struct r_glsl_permutation_s;
717 typedef struct r_glsl_permutation_s
718 {
719         /// hash lookup data
720         struct r_glsl_permutation_s *hashnext;
721         unsigned int mode;
722         unsigned int permutation;
723
724         /// indicates if we have tried compiling this permutation already
725         qboolean compiled;
726         /// 0 if compilation failed
727         int program;
728         // texture units assigned to each detected uniform
729         int tex_Texture_First;
730         int tex_Texture_Second;
731         int tex_Texture_GammaRamps;
732         int tex_Texture_Normal;
733         int tex_Texture_Color;
734         int tex_Texture_Gloss;
735         int tex_Texture_Glow;
736         int tex_Texture_SecondaryNormal;
737         int tex_Texture_SecondaryColor;
738         int tex_Texture_SecondaryGloss;
739         int tex_Texture_SecondaryGlow;
740         int tex_Texture_Pants;
741         int tex_Texture_Shirt;
742         int tex_Texture_FogHeightTexture;
743         int tex_Texture_FogMask;
744         int tex_Texture_Lightmap;
745         int tex_Texture_Deluxemap;
746         int tex_Texture_Attenuation;
747         int tex_Texture_Cube;
748         int tex_Texture_Refraction;
749         int tex_Texture_Reflection;
750         int tex_Texture_ShadowMap2D;
751         int tex_Texture_CubeProjection;
752         int tex_Texture_ScreenNormalMap;
753         int tex_Texture_ScreenDiffuse;
754         int tex_Texture_ScreenSpecular;
755         int tex_Texture_ReflectMask;
756         int tex_Texture_ReflectCube;
757         int tex_Texture_BounceGrid;
758         /// locations of detected uniforms in program object, or -1 if not found
759         int loc_Texture_First;
760         int loc_Texture_Second;
761         int loc_Texture_GammaRamps;
762         int loc_Texture_Normal;
763         int loc_Texture_Color;
764         int loc_Texture_Gloss;
765         int loc_Texture_Glow;
766         int loc_Texture_SecondaryNormal;
767         int loc_Texture_SecondaryColor;
768         int loc_Texture_SecondaryGloss;
769         int loc_Texture_SecondaryGlow;
770         int loc_Texture_Pants;
771         int loc_Texture_Shirt;
772         int loc_Texture_FogHeightTexture;
773         int loc_Texture_FogMask;
774         int loc_Texture_Lightmap;
775         int loc_Texture_Deluxemap;
776         int loc_Texture_Attenuation;
777         int loc_Texture_Cube;
778         int loc_Texture_Refraction;
779         int loc_Texture_Reflection;
780         int loc_Texture_ShadowMap2D;
781         int loc_Texture_CubeProjection;
782         int loc_Texture_ScreenNormalMap;
783         int loc_Texture_ScreenDiffuse;
784         int loc_Texture_ScreenSpecular;
785         int loc_Texture_ReflectMask;
786         int loc_Texture_ReflectCube;
787         int loc_Texture_BounceGrid;
788         int loc_Alpha;
789         int loc_BloomBlur_Parameters;
790         int loc_ClientTime;
791         int loc_Color_Ambient;
792         int loc_Color_Diffuse;
793         int loc_Color_Specular;
794         int loc_Color_Glow;
795         int loc_Color_Pants;
796         int loc_Color_Shirt;
797         int loc_DeferredColor_Ambient;
798         int loc_DeferredColor_Diffuse;
799         int loc_DeferredColor_Specular;
800         int loc_DeferredMod_Diffuse;
801         int loc_DeferredMod_Specular;
802         int loc_DistortScaleRefractReflect;
803         int loc_EyePosition;
804         int loc_FogColor;
805         int loc_FogHeightFade;
806         int loc_FogPlane;
807         int loc_FogPlaneViewDist;
808         int loc_FogRangeRecip;
809         int loc_LightColor;
810         int loc_LightDir;
811         int loc_LightPosition;
812         int loc_OffsetMapping_ScaleSteps;
813         int loc_OffsetMapping_LodDistance;
814         int loc_OffsetMapping_Bias;
815         int loc_PixelSize;
816         int loc_ReflectColor;
817         int loc_ReflectFactor;
818         int loc_ReflectOffset;
819         int loc_RefractColor;
820         int loc_Saturation;
821         int loc_ScreenCenterRefractReflect;
822         int loc_ScreenScaleRefractReflect;
823         int loc_ScreenToDepth;
824         int loc_ShadowMap_Parameters;
825         int loc_ShadowMap_TextureScale;
826         int loc_SpecularPower;
827         int loc_Skeletal_Transform12;
828         int loc_UserVec1;
829         int loc_UserVec2;
830         int loc_UserVec3;
831         int loc_UserVec4;
832         int loc_ViewTintColor;
833         int loc_ViewToLight;
834         int loc_ModelToLight;
835         int loc_TexMatrix;
836         int loc_BackgroundTexMatrix;
837         int loc_ModelViewProjectionMatrix;
838         int loc_ModelViewMatrix;
839         int loc_PixelToScreenTexCoord;
840         int loc_ModelToReflectCube;
841         int loc_ShadowMapMatrix;
842         int loc_BloomColorSubtract;
843         int loc_NormalmapScrollBlend;
844         int loc_BounceGridMatrix;
845         int loc_BounceGridIntensity;
846 }
847 r_glsl_permutation_t;
848
849 #define SHADERPERMUTATION_HASHSIZE 256
850
851
852 // non-degradable "lightweight" shader parameters to keep the permutations simpler
853 // these can NOT degrade! only use for simple stuff
854 enum
855 {
856         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
857         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
858         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
859         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
861         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
862         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
863         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
864         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
865         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
866         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
867         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
868         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
869 };
870 #define SHADERSTATICPARMS_COUNT 13
871
872 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
873 static int shaderstaticparms_count = 0;
874
875 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
876 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
877
878 extern qboolean r_shadow_shadowmapsampler;
879 extern int r_shadow_shadowmappcf;
880 qboolean R_CompileShader_CheckStaticParms(void)
881 {
882         static int r_compileshader_staticparms_save[1];
883         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
884         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
885
886         // detect all
887         if (r_glsl_saturation_redcompensate.integer)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
889         if (r_glsl_vertextextureblend_usebothalphas.integer)
890                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
891         if (r_shadow_glossexact.integer)
892                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
893         if (r_glsl_postprocess.integer)
894         {
895                 if (r_glsl_postprocess_uservec1_enable.integer)
896                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
897                 if (r_glsl_postprocess_uservec2_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
899                 if (r_glsl_postprocess_uservec3_enable.integer)
900                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
901                 if (r_glsl_postprocess_uservec4_enable.integer)
902                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
903         }
904         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
906
907         if (r_shadow_shadowmapsampler)
908                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
909         if (r_shadow_shadowmappcf > 1)
910                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
911         else if (r_shadow_shadowmappcf)
912                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
913         if (r_celshading.integer)
914                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
915         if (r_celoutlines.integer)
916                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
917
918         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
919 }
920
921 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
922         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
923                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
924         else \
925                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
926 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
927 {
928         shaderstaticparms_count = 0;
929
930         // emit all
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
936         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
937         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
938         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
939         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
940         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
941         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
942         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
943         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
944 }
945
946 /// information about each possible shader permutation
947 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
948 /// currently selected permutation
949 r_glsl_permutation_t *r_glsl_permutation;
950 /// storage for permutations linked in the hash table
951 memexpandablearray_t r_glsl_permutationarray;
952
953 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
954 {
955         //unsigned int hashdepth = 0;
956         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
957         r_glsl_permutation_t *p;
958         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
959         {
960                 if (p->mode == mode && p->permutation == permutation)
961                 {
962                         //if (hashdepth > 10)
963                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
964                         return p;
965                 }
966                 //hashdepth++;
967         }
968         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
969         p->mode = mode;
970         p->permutation = permutation;
971         p->hashnext = r_glsl_permutationhash[mode][hashindex];
972         r_glsl_permutationhash[mode][hashindex] = p;
973         //if (hashdepth > 10)
974         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
975         return p;
976 }
977
978 static char *R_ShaderStrCat(const char **strings)
979 {
980         char *string, *s;
981         const char **p = strings;
982         const char *t;
983         size_t len = 0;
984         for (p = strings;(t = *p);p++)
985                 len += strlen(t);
986         len++;
987         s = string = (char *)Mem_Alloc(r_main_mempool, len);
988         len = 0;
989         for (p = strings;(t = *p);p++)
990         {
991                 len = strlen(t);
992                 memcpy(s, t, len);
993                 s += len;
994         }
995         *s = 0;
996         return string;
997 }
998
999 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1000 {
1001         char *shaderstring;
1002         if (!filename || !filename[0])
1003                 return NULL;
1004         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1005         if (!strcmp(filename, "glsl/default.glsl"))
1006         {
1007                 if (builtinonly)
1008                         return R_ShaderStrCat(builtinshaderstrings);
1009                 if (!glslshaderstring)
1010                 {
1011                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1012                         if (glslshaderstring)
1013                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1014                         else
1015                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1016                 }
1017                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1018                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1019                 return shaderstring;
1020         }
1021         if (!strcmp(filename, "hlsl/default.hlsl"))
1022         {
1023                 if (builtinonly)
1024                         return R_ShaderStrCat(builtinhlslshaderstrings);
1025                 if (!hlslshaderstring)
1026                 {
1027                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1028                         if (hlslshaderstring)
1029                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1030                         else
1031                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1032                 }
1033                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1034                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1035                 return shaderstring;
1036         }
1037         // we don't have builtin strings for any other files
1038         if (builtinonly)
1039                 return NULL;
1040         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1041         if (shaderstring)
1042         {
1043                 if (printfromdisknotice)
1044                         Con_DPrintf("from disk %s... ", filename);
1045                 return shaderstring;
1046         }
1047         return shaderstring;
1048 }
1049
1050 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1051 {
1052         int i;
1053         int sampler;
1054         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1055         char *sourcestring;
1056         char permutationname[256];
1057         int vertstrings_count = 0;
1058         int geomstrings_count = 0;
1059         int fragstrings_count = 0;
1060         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1061         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1062         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1063
1064         if (p->compiled)
1065                 return;
1066         p->compiled = true;
1067         p->program = 0;
1068
1069         permutationname[0] = 0;
1070         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1071
1072         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1073
1074         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1075         if(vid.support.gl20shaders130)
1076         {
1077                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1078                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1079                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1080                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1081                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1082                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1083         }
1084
1085         // the first pretext is which type of shader to compile as
1086         // (later these will all be bound together as a program object)
1087         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1088         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1089         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1090
1091         // the second pretext is the mode (for example a light source)
1092         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1093         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1094         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1095         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1096
1097         // now add all the permutation pretexts
1098         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1099         {
1100                 if (permutation & (1<<i))
1101                 {
1102                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1103                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1104                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1105                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1106                 }
1107                 else
1108                 {
1109                         // keep line numbers correct
1110                         vertstrings_list[vertstrings_count++] = "\n";
1111                         geomstrings_list[geomstrings_count++] = "\n";
1112                         fragstrings_list[fragstrings_count++] = "\n";
1113                 }
1114         }
1115
1116         // add static parms
1117         R_CompileShader_AddStaticParms(mode, permutation);
1118         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1119         vertstrings_count += shaderstaticparms_count;
1120         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1121         geomstrings_count += shaderstaticparms_count;
1122         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1123         fragstrings_count += shaderstaticparms_count;
1124
1125         // now append the shader text itself
1126         vertstrings_list[vertstrings_count++] = sourcestring;
1127         geomstrings_list[geomstrings_count++] = sourcestring;
1128         fragstrings_list[fragstrings_count++] = sourcestring;
1129
1130         // compile the shader program
1131         if (vertstrings_count + geomstrings_count + fragstrings_count)
1132                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1133         if (p->program)
1134         {
1135                 CHECKGLERROR
1136                 qglUseProgram(p->program);CHECKGLERROR
1137                 // look up all the uniform variable names we care about, so we don't
1138                 // have to look them up every time we set them
1139
1140                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1141                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1142                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1143                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1144                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1145                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1146                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1147                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1148                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1149                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1150                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1151                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1152                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1153                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1154                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1155                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1156                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1157                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1158                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1159                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1160                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1161                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1162                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1163                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1164                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1165                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1166                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1167                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1168                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1169                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1170                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1171                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1172                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1173                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1174                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1175                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1176                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1177                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1178                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1179                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1180                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1181                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1182                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1183                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1184                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1185                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1186                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1187                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1188                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1189                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1190                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1191                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1192                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1193                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1194                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1195                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1196                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1197                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1198                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1199                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1200                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1201                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1202                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1203                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1204                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1205                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1206                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1207                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1208                 p->loc_Skeletal_Transform12       = qglGetUniformLocation(p->program, "Skeletal_Transform12");
1209                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1210                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1211                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1212                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1213                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1214                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1215                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1216                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1217                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1218                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1219                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1220                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1221                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1222                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1223                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1224                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1225                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1226                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1227                 // initialize the samplers to refer to the texture units we use
1228                 p->tex_Texture_First = -1;
1229                 p->tex_Texture_Second = -1;
1230                 p->tex_Texture_GammaRamps = -1;
1231                 p->tex_Texture_Normal = -1;
1232                 p->tex_Texture_Color = -1;
1233                 p->tex_Texture_Gloss = -1;
1234                 p->tex_Texture_Glow = -1;
1235                 p->tex_Texture_SecondaryNormal = -1;
1236                 p->tex_Texture_SecondaryColor = -1;
1237                 p->tex_Texture_SecondaryGloss = -1;
1238                 p->tex_Texture_SecondaryGlow = -1;
1239                 p->tex_Texture_Pants = -1;
1240                 p->tex_Texture_Shirt = -1;
1241                 p->tex_Texture_FogHeightTexture = -1;
1242                 p->tex_Texture_FogMask = -1;
1243                 p->tex_Texture_Lightmap = -1;
1244                 p->tex_Texture_Deluxemap = -1;
1245                 p->tex_Texture_Attenuation = -1;
1246                 p->tex_Texture_Cube = -1;
1247                 p->tex_Texture_Refraction = -1;
1248                 p->tex_Texture_Reflection = -1;
1249                 p->tex_Texture_ShadowMap2D = -1;
1250                 p->tex_Texture_CubeProjection = -1;
1251                 p->tex_Texture_ScreenNormalMap = -1;
1252                 p->tex_Texture_ScreenDiffuse = -1;
1253                 p->tex_Texture_ScreenSpecular = -1;
1254                 p->tex_Texture_ReflectMask = -1;
1255                 p->tex_Texture_ReflectCube = -1;
1256                 p->tex_Texture_BounceGrid = -1;
1257                 sampler = 0;
1258                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1259                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1260                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1261                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1262                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1263                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1264                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1265                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1266                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1267                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1268                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1269                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1270                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1271                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1272                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1273                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1274                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1275                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1276                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1277                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1278                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1279                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1280                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1281                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1282                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1283                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1284                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1285                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1286                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1287                 CHECKGLERROR
1288                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1289         }
1290         else
1291                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1292
1293         // free the strings
1294         if (sourcestring)
1295                 Mem_Free(sourcestring);
1296 }
1297
1298 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1299 {
1300         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1301         if (r_glsl_permutation != perm)
1302         {
1303                 r_glsl_permutation = perm;
1304                 if (!r_glsl_permutation->program)
1305                 {
1306                         if (!r_glsl_permutation->compiled)
1307                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1308                         if (!r_glsl_permutation->program)
1309                         {
1310                                 // remove features until we find a valid permutation
1311                                 int i;
1312                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1313                                 {
1314                                         // reduce i more quickly whenever it would not remove any bits
1315                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1316                                         if (!(permutation & j))
1317                                                 continue;
1318                                         permutation -= j;
1319                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1320                                         if (!r_glsl_permutation->compiled)
1321                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1322                                         if (r_glsl_permutation->program)
1323                                                 break;
1324                                 }
1325                                 if (i >= SHADERPERMUTATION_COUNT)
1326                                 {
1327                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1328                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1329                                         qglUseProgram(0);CHECKGLERROR
1330                                         return; // no bit left to clear, entire mode is broken
1331                                 }
1332                         }
1333                 }
1334                 CHECKGLERROR
1335                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1336         }
1337         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1338         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1339         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1340 }
1341
1342 #ifdef SUPPORTD3D
1343
1344 #ifdef SUPPORTD3D
1345 #include <d3d9.h>
1346 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1347 extern D3DCAPS9 vid_d3d9caps;
1348 #endif
1349
1350 struct r_hlsl_permutation_s;
1351 typedef struct r_hlsl_permutation_s
1352 {
1353         /// hash lookup data
1354         struct r_hlsl_permutation_s *hashnext;
1355         unsigned int mode;
1356         unsigned int permutation;
1357
1358         /// indicates if we have tried compiling this permutation already
1359         qboolean compiled;
1360         /// NULL if compilation failed
1361         IDirect3DVertexShader9 *vertexshader;
1362         IDirect3DPixelShader9 *pixelshader;
1363 }
1364 r_hlsl_permutation_t;
1365
1366 typedef enum D3DVSREGISTER_e
1367 {
1368         D3DVSREGISTER_TexMatrix = 0, // float4x4
1369         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1370         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1371         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1372         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1373         D3DVSREGISTER_ModelToLight = 20, // float4x4
1374         D3DVSREGISTER_EyePosition = 24,
1375         D3DVSREGISTER_FogPlane = 25,
1376         D3DVSREGISTER_LightDir = 26,
1377         D3DVSREGISTER_LightPosition = 27,
1378 }
1379 D3DVSREGISTER_t;
1380
1381 typedef enum D3DPSREGISTER_e
1382 {
1383         D3DPSREGISTER_Alpha = 0,
1384         D3DPSREGISTER_BloomBlur_Parameters = 1,
1385         D3DPSREGISTER_ClientTime = 2,
1386         D3DPSREGISTER_Color_Ambient = 3,
1387         D3DPSREGISTER_Color_Diffuse = 4,
1388         D3DPSREGISTER_Color_Specular = 5,
1389         D3DPSREGISTER_Color_Glow = 6,
1390         D3DPSREGISTER_Color_Pants = 7,
1391         D3DPSREGISTER_Color_Shirt = 8,
1392         D3DPSREGISTER_DeferredColor_Ambient = 9,
1393         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1394         D3DPSREGISTER_DeferredColor_Specular = 11,
1395         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1396         D3DPSREGISTER_DeferredMod_Specular = 13,
1397         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1398         D3DPSREGISTER_EyePosition = 15, // unused
1399         D3DPSREGISTER_FogColor = 16,
1400         D3DPSREGISTER_FogHeightFade = 17,
1401         D3DPSREGISTER_FogPlane = 18,
1402         D3DPSREGISTER_FogPlaneViewDist = 19,
1403         D3DPSREGISTER_FogRangeRecip = 20,
1404         D3DPSREGISTER_LightColor = 21,
1405         D3DPSREGISTER_LightDir = 22, // unused
1406         D3DPSREGISTER_LightPosition = 23,
1407         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1408         D3DPSREGISTER_PixelSize = 25,
1409         D3DPSREGISTER_ReflectColor = 26,
1410         D3DPSREGISTER_ReflectFactor = 27,
1411         D3DPSREGISTER_ReflectOffset = 28,
1412         D3DPSREGISTER_RefractColor = 29,
1413         D3DPSREGISTER_Saturation = 30,
1414         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1415         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1416         D3DPSREGISTER_ScreenToDepth = 33,
1417         D3DPSREGISTER_ShadowMap_Parameters = 34,
1418         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1419         D3DPSREGISTER_SpecularPower = 36,
1420         D3DPSREGISTER_UserVec1 = 37,
1421         D3DPSREGISTER_UserVec2 = 38,
1422         D3DPSREGISTER_UserVec3 = 39,
1423         D3DPSREGISTER_UserVec4 = 40,
1424         D3DPSREGISTER_ViewTintColor = 41,
1425         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1426         D3DPSREGISTER_BloomColorSubtract = 43,
1427         D3DPSREGISTER_ViewToLight = 44, // float4x4
1428         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1429         D3DPSREGISTER_NormalmapScrollBlend = 52,
1430         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1431         D3DPSREGISTER_OffsetMapping_Bias = 54,
1432         // next at 54
1433 }
1434 D3DPSREGISTER_t;
1435
1436 /// information about each possible shader permutation
1437 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1438 /// currently selected permutation
1439 r_hlsl_permutation_t *r_hlsl_permutation;
1440 /// storage for permutations linked in the hash table
1441 memexpandablearray_t r_hlsl_permutationarray;
1442
1443 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1444 {
1445         //unsigned int hashdepth = 0;
1446         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1447         r_hlsl_permutation_t *p;
1448         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1449         {
1450                 if (p->mode == mode && p->permutation == permutation)
1451                 {
1452                         //if (hashdepth > 10)
1453                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1454                         return p;
1455                 }
1456                 //hashdepth++;
1457         }
1458         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1459         p->mode = mode;
1460         p->permutation = permutation;
1461         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1462         r_hlsl_permutationhash[mode][hashindex] = p;
1463         //if (hashdepth > 10)
1464         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1465         return p;
1466 }
1467
1468 #include <d3dx9.h>
1469 //#include <d3dx9shader.h>
1470 //#include <d3dx9mesh.h>
1471
1472 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1473 {
1474         DWORD *vsbin = NULL;
1475         DWORD *psbin = NULL;
1476         fs_offset_t vsbinsize;
1477         fs_offset_t psbinsize;
1478 //      IDirect3DVertexShader9 *vs = NULL;
1479 //      IDirect3DPixelShader9 *ps = NULL;
1480         ID3DXBuffer *vslog = NULL;
1481         ID3DXBuffer *vsbuffer = NULL;
1482         ID3DXConstantTable *vsconstanttable = NULL;
1483         ID3DXBuffer *pslog = NULL;
1484         ID3DXBuffer *psbuffer = NULL;
1485         ID3DXConstantTable *psconstanttable = NULL;
1486         int vsresult = 0;
1487         int psresult = 0;
1488         char temp[MAX_INPUTLINE];
1489         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1490         char vabuf[1024];
1491         qboolean debugshader = gl_paranoid.integer != 0;
1492         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1493         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1494         if (!debugshader)
1495         {
1496                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1497                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1498         }
1499         if ((!vsbin && vertstring) || (!psbin && fragstring))
1500         {
1501                 const char* dllnames_d3dx9 [] =
1502                 {
1503                         "d3dx9_43.dll",
1504                         "d3dx9_42.dll",
1505                         "d3dx9_41.dll",
1506                         "d3dx9_40.dll",
1507                         "d3dx9_39.dll",
1508                         "d3dx9_38.dll",
1509                         "d3dx9_37.dll",
1510                         "d3dx9_36.dll",
1511                         "d3dx9_35.dll",
1512                         "d3dx9_34.dll",
1513                         "d3dx9_33.dll",
1514                         "d3dx9_32.dll",
1515                         "d3dx9_31.dll",
1516                         "d3dx9_30.dll",
1517                         "d3dx9_29.dll",
1518                         "d3dx9_28.dll",
1519                         "d3dx9_27.dll",
1520                         "d3dx9_26.dll",
1521                         "d3dx9_25.dll",
1522                         "d3dx9_24.dll",
1523                         NULL
1524                 };
1525                 dllhandle_t d3dx9_dll = NULL;
1526                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1527                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1528                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1529                 dllfunction_t d3dx9_dllfuncs[] =
1530                 {
1531                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1532                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1533                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1534                         {NULL, NULL}
1535                 };
1536                 // 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...
1537 #ifndef ID3DXBuffer_GetBufferPointer
1538 #if !defined(__cplusplus) || defined(CINTERFACE)
1539 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1540 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1541 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1542 #else
1543 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1544 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1545 #define ID3DXBuffer_Release(p)            (p)->Release()
1546 #endif
1547 #endif
1548                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1549                 {
1550                         DWORD shaderflags = 0;
1551                         if (debugshader)
1552                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1553                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1554                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1555                         if (vertstring && vertstring[0])
1556                         {
1557                                 if (debugshader)
1558                                 {
1559                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1560                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1561                                 }
1562                                 else
1563                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1564                                 if (vsbuffer)
1565                                 {
1566                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1567                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1568                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1569                                         ID3DXBuffer_Release(vsbuffer);
1570                                 }
1571                                 if (vslog)
1572                                 {
1573                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1574                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1575                                         ID3DXBuffer_Release(vslog);
1576                                 }
1577                         }
1578                         if (fragstring && fragstring[0])
1579                         {
1580                                 if (debugshader)
1581                                 {
1582                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1583                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1584                                 }
1585                                 else
1586                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1587                                 if (psbuffer)
1588                                 {
1589                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1590                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1591                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1592                                         ID3DXBuffer_Release(psbuffer);
1593                                 }
1594                                 if (pslog)
1595                                 {
1596                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1597                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1598                                         ID3DXBuffer_Release(pslog);
1599                                 }
1600                         }
1601                         Sys_UnloadLibrary(&d3dx9_dll);
1602                 }
1603                 else
1604                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1605         }
1606         if (vsbin && psbin)
1607         {
1608                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1609                 if (FAILED(vsresult))
1610                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1611                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1612                 if (FAILED(psresult))
1613                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1614         }
1615         // free the shader data
1616         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1617         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1618 }
1619
1620 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1621 {
1622         int i;
1623         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1624         int vertstring_length = 0;
1625         int geomstring_length = 0;
1626         int fragstring_length = 0;
1627         char *t;
1628         char *sourcestring;
1629         char *vertstring, *geomstring, *fragstring;
1630         char permutationname[256];
1631         char cachename[256];
1632         int vertstrings_count = 0;
1633         int geomstrings_count = 0;
1634         int fragstrings_count = 0;
1635         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1636         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1637         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1638
1639         if (p->compiled)
1640                 return;
1641         p->compiled = true;
1642         p->vertexshader = NULL;
1643         p->pixelshader = NULL;
1644
1645         permutationname[0] = 0;
1646         cachename[0] = 0;
1647         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1648
1649         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1650         strlcat(cachename, "hlsl/", sizeof(cachename));
1651
1652         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1653         vertstrings_count = 0;
1654         geomstrings_count = 0;
1655         fragstrings_count = 0;
1656         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1657         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1658         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1659
1660         // the first pretext is which type of shader to compile as
1661         // (later these will all be bound together as a program object)
1662         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1663         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1664         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1665
1666         // the second pretext is the mode (for example a light source)
1667         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1668         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1669         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1670         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1671         strlcat(cachename, modeinfo->name, sizeof(cachename));
1672
1673         // now add all the permutation pretexts
1674         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1675         {
1676                 if (permutation & (1<<i))
1677                 {
1678                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1679                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1680                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1681                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1682                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1683                 }
1684                 else
1685                 {
1686                         // keep line numbers correct
1687                         vertstrings_list[vertstrings_count++] = "\n";
1688                         geomstrings_list[geomstrings_count++] = "\n";
1689                         fragstrings_list[fragstrings_count++] = "\n";
1690                 }
1691         }
1692
1693         // add static parms
1694         R_CompileShader_AddStaticParms(mode, permutation);
1695         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1696         vertstrings_count += shaderstaticparms_count;
1697         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1698         geomstrings_count += shaderstaticparms_count;
1699         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1700         fragstrings_count += shaderstaticparms_count;
1701
1702         // replace spaces in the cachename with _ characters
1703         for (i = 0;cachename[i];i++)
1704                 if (cachename[i] == ' ')
1705                         cachename[i] = '_';
1706
1707         // now append the shader text itself
1708         vertstrings_list[vertstrings_count++] = sourcestring;
1709         geomstrings_list[geomstrings_count++] = sourcestring;
1710         fragstrings_list[fragstrings_count++] = sourcestring;
1711
1712         vertstring_length = 0;
1713         for (i = 0;i < vertstrings_count;i++)
1714                 vertstring_length += strlen(vertstrings_list[i]);
1715         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1716         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1717                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1718
1719         geomstring_length = 0;
1720         for (i = 0;i < geomstrings_count;i++)
1721                 geomstring_length += strlen(geomstrings_list[i]);
1722         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1723         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1724                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1725
1726         fragstring_length = 0;
1727         for (i = 0;i < fragstrings_count;i++)
1728                 fragstring_length += strlen(fragstrings_list[i]);
1729         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1730         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1731                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1732
1733         // try to load the cached shader, or generate one
1734         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1735
1736         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1737                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1738         else
1739                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1740
1741         // free the strings
1742         if (vertstring)
1743                 Mem_Free(vertstring);
1744         if (geomstring)
1745                 Mem_Free(geomstring);
1746         if (fragstring)
1747                 Mem_Free(fragstring);
1748         if (sourcestring)
1749                 Mem_Free(sourcestring);
1750 }
1751
1752 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1753 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1754 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);}
1755 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);}
1756 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);}
1757 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);}
1758
1759 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1760 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1761 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);}
1762 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);}
1763 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);}
1764 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);}
1765
1766 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1767 {
1768         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1769         if (r_hlsl_permutation != perm)
1770         {
1771                 r_hlsl_permutation = perm;
1772                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1773                 {
1774                         if (!r_hlsl_permutation->compiled)
1775                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1776                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1777                         {
1778                                 // remove features until we find a valid permutation
1779                                 int i;
1780                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1781                                 {
1782                                         // reduce i more quickly whenever it would not remove any bits
1783                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1784                                         if (!(permutation & j))
1785                                                 continue;
1786                                         permutation -= j;
1787                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1788                                         if (!r_hlsl_permutation->compiled)
1789                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1790                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1791                                                 break;
1792                                 }
1793                                 if (i >= SHADERPERMUTATION_COUNT)
1794                                 {
1795                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1796                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1797                                         return; // no bit left to clear, entire mode is broken
1798                                 }
1799                         }
1800                 }
1801                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1802                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1803         }
1804         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1805         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1806         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1807 }
1808 #endif
1809
1810 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1811 {
1812         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1813         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1814         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1815         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1816 }
1817
1818 void R_GLSL_Restart_f(void)
1819 {
1820         unsigned int i, limit;
1821         if (glslshaderstring)
1822                 Mem_Free(glslshaderstring);
1823         glslshaderstring = NULL;
1824         if (hlslshaderstring)
1825                 Mem_Free(hlslshaderstring);
1826         hlslshaderstring = NULL;
1827         switch(vid.renderpath)
1828         {
1829         case RENDERPATH_D3D9:
1830 #ifdef SUPPORTD3D
1831                 {
1832                         r_hlsl_permutation_t *p;
1833                         r_hlsl_permutation = NULL;
1834                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1835                         for (i = 0;i < limit;i++)
1836                         {
1837                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1838                                 {
1839                                         if (p->vertexshader)
1840                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1841                                         if (p->pixelshader)
1842                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1843                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1844                                 }
1845                         }
1846                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1847                 }
1848 #endif
1849                 break;
1850         case RENDERPATH_D3D10:
1851                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1852                 break;
1853         case RENDERPATH_D3D11:
1854                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1855                 break;
1856         case RENDERPATH_GL20:
1857         case RENDERPATH_GLES2:
1858                 {
1859                         r_glsl_permutation_t *p;
1860                         r_glsl_permutation = NULL;
1861                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1862                         for (i = 0;i < limit;i++)
1863                         {
1864                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1865                                 {
1866                                         GL_Backend_FreeProgram(p->program);
1867                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1868                                 }
1869                         }
1870                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1871                 }
1872                 break;
1873         case RENDERPATH_GL11:
1874         case RENDERPATH_GL13:
1875         case RENDERPATH_GLES1:
1876                 break;
1877         case RENDERPATH_SOFT:
1878                 break;
1879         }
1880 }
1881
1882 static void R_GLSL_DumpShader_f(void)
1883 {
1884         int i, language, mode, dupe;
1885         char *text;
1886         shadermodeinfo_t *modeinfo;
1887         qfile_t *file;
1888
1889         for (language = 0;language < 2;language++)
1890         {
1891                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1892                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1893                 {
1894                         // don't dump the same file multiple times (most or all shaders come from the same file)
1895                         for (dupe = mode - 1;dupe >= 0;dupe--)
1896                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1897                                         break;
1898                         if (dupe >= 0)
1899                                 continue;
1900                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1901                         if (!text)
1902                                 continue;
1903                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1904                         if (file)
1905                         {
1906                                 FS_Print(file, "/* The engine may define the following macros:\n");
1907                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1908                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1909                                         FS_Print(file, modeinfo[i].pretext);
1910                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1911                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1912                                 FS_Print(file, "*/\n");
1913                                 FS_Print(file, text);
1914                                 FS_Close(file);
1915                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1916                         }
1917                         else
1918                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1919                         Mem_Free(text);
1920                 }
1921         }
1922 }
1923
1924 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1925 {
1926         unsigned int permutation = 0;
1927         if (r_trippy.integer && !notrippy)
1928                 permutation |= SHADERPERMUTATION_TRIPPY;
1929         permutation |= SHADERPERMUTATION_VIEWTINT;
1930         if (first)
1931                 permutation |= SHADERPERMUTATION_DIFFUSE;
1932         if (second)
1933                 permutation |= SHADERPERMUTATION_SPECULAR;
1934         if (texturemode == GL_MODULATE)
1935                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1936         else if (texturemode == GL_ADD)
1937                 permutation |= SHADERPERMUTATION_GLOW;
1938         else if (texturemode == GL_DECAL)
1939                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1940         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1941                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1942         if (suppresstexalpha)
1943                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1944         if (!second)
1945                 texturemode = GL_MODULATE;
1946         if (vid.allowalphatocoverage)
1947                 GL_AlphaToCoverage(false);
1948         switch (vid.renderpath)
1949         {
1950         case RENDERPATH_D3D9:
1951 #ifdef SUPPORTD3D
1952                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1953                 R_Mesh_TexBind(GL20TU_FIRST , first );
1954                 R_Mesh_TexBind(GL20TU_SECOND, second);
1955                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1956                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1957 #endif
1958                 break;
1959         case RENDERPATH_D3D10:
1960                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961                 break;
1962         case RENDERPATH_D3D11:
1963                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1964                 break;
1965         case RENDERPATH_GL20:
1966         case RENDERPATH_GLES2:
1967                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1968                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1969                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1970                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1971                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1972                 break;
1973         case RENDERPATH_GL13:
1974         case RENDERPATH_GLES1:
1975                 R_Mesh_TexBind(0, first );
1976                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1977                 R_Mesh_TexBind(1, second);
1978                 if (second)
1979                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1980                 break;
1981         case RENDERPATH_GL11:
1982                 R_Mesh_TexBind(0, first );
1983                 break;
1984         case RENDERPATH_SOFT:
1985                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1986                 R_Mesh_TexBind(GL20TU_FIRST , first );
1987                 R_Mesh_TexBind(GL20TU_SECOND, second);
1988                 break;
1989         }
1990 }
1991
1992 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1993 {
1994         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1995 }
1996
1997 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
1998 {
1999         unsigned int permutation = 0;
2000         if (r_trippy.integer && !notrippy)
2001                 permutation |= SHADERPERMUTATION_TRIPPY;
2002         if (depthrgb)
2003                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2004         if (skeletal)
2005                 permutation |= SHADERPERMUTATION_SKELETAL;
2006
2007         if (vid.allowalphatocoverage)
2008                 GL_AlphaToCoverage(false);
2009         switch (vid.renderpath)
2010         {
2011         case RENDERPATH_D3D9:
2012 #ifdef SUPPORTD3D
2013                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2014 #endif
2015                 break;
2016         case RENDERPATH_D3D10:
2017                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2018                 break;
2019         case RENDERPATH_D3D11:
2020                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2021                 break;
2022         case RENDERPATH_GL20:
2023         case RENDERPATH_GLES2:
2024                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2025                 break;
2026         case RENDERPATH_GL13:
2027         case RENDERPATH_GLES1:
2028                 R_Mesh_TexBind(0, 0);
2029                 R_Mesh_TexBind(1, 0);
2030                 break;
2031         case RENDERPATH_GL11:
2032                 R_Mesh_TexBind(0, 0);
2033                 break;
2034         case RENDERPATH_SOFT:
2035                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2036                 break;
2037         }
2038 }
2039
2040 extern qboolean r_shadow_usingdeferredprepass;
2041 extern rtexture_t *r_shadow_attenuationgradienttexture;
2042 extern rtexture_t *r_shadow_attenuation2dtexture;
2043 extern rtexture_t *r_shadow_attenuation3dtexture;
2044 extern qboolean r_shadow_usingshadowmap2d;
2045 extern qboolean r_shadow_usingshadowmaportho;
2046 extern float r_shadow_shadowmap_texturescale[2];
2047 extern float r_shadow_shadowmap_parameters[4];
2048 extern qboolean r_shadow_shadowmapvsdct;
2049 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2050 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2051 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2052 extern matrix4x4_t r_shadow_shadowmapmatrix;
2053 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2054 extern int r_shadow_prepass_width;
2055 extern int r_shadow_prepass_height;
2056 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2057 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2058 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2059 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2060
2061 #define BLENDFUNC_ALLOWS_COLORMOD      1
2062 #define BLENDFUNC_ALLOWS_FOG           2
2063 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2064 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2065 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2066 static int R_BlendFuncFlags(int src, int dst)
2067 {
2068         int r = 0;
2069
2070         // a blendfunc allows colormod if:
2071         // a) it can never keep the destination pixel invariant, or
2072         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2073         // this is to prevent unintended side effects from colormod
2074
2075         // a blendfunc allows fog if:
2076         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2077         // this is to prevent unintended side effects from fog
2078
2079         // these checks are the output of fogeval.pl
2080
2081         r |= BLENDFUNC_ALLOWS_COLORMOD;
2082         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2083         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2084         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2085         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2086         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2087         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2088         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2089         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2090         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2091         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2092         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2093         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2094         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2095         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2096         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2100         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2101         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2102         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2103
2104         return r;
2105 }
2106
2107 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)
2108 {
2109         // select a permutation of the lighting shader appropriate to this
2110         // combination of texture, entity, light source, and fogging, only use the
2111         // minimum features necessary to avoid wasting rendering time in the
2112         // fragment shader on features that are not being used
2113         unsigned int permutation = 0;
2114         unsigned int mode = 0;
2115         int blendfuncflags;
2116         static float dummy_colormod[3] = {1, 1, 1};
2117         float *colormod = rsurface.colormod;
2118         float m16f[16];
2119         matrix4x4_t tempmatrix;
2120         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2121         if (r_trippy.integer && !notrippy)
2122                 permutation |= SHADERPERMUTATION_TRIPPY;
2123         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2124                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2125         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2126                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2127         if (rsurfacepass == RSURFPASS_BACKGROUND)
2128         {
2129                 // distorted background
2130                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2131                 {
2132                         mode = SHADERMODE_WATER;
2133                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2134                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2135                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2136                         {
2137                                 // this is the right thing to do for wateralpha
2138                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2139                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2140                         }
2141                         else
2142                         {
2143                                 // this is the right thing to do for entity alpha
2144                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2145                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146                         }
2147                 }
2148                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2149                 {
2150                         mode = SHADERMODE_REFRACTION;
2151                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2152                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2153                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2154                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2155                 }
2156                 else
2157                 {
2158                         mode = SHADERMODE_GENERIC;
2159                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2160                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2161                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2162                 }
2163                 if (vid.allowalphatocoverage)
2164                         GL_AlphaToCoverage(false);
2165         }
2166         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2167         {
2168                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2169                 {
2170                         switch(rsurface.texture->offsetmapping)
2171                         {
2172                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2173                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2174                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2175                         case OFFSETMAPPING_OFF: break;
2176                         }
2177                 }
2178                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2179                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2180                 // normalmap (deferred prepass), may use alpha test on diffuse
2181                 mode = SHADERMODE_DEFERREDGEOMETRY;
2182                 GL_BlendFunc(GL_ONE, GL_ZERO);
2183                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2184                 if (vid.allowalphatocoverage)
2185                         GL_AlphaToCoverage(false);
2186         }
2187         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2188         {
2189                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2190                 {
2191                         switch(rsurface.texture->offsetmapping)
2192                         {
2193                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2194                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2195                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2196                         case OFFSETMAPPING_OFF: break;
2197                         }
2198                 }
2199                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2200                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2201                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2202                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2203                 // light source
2204                 mode = SHADERMODE_LIGHTSOURCE;
2205                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2206                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2207                 if (diffusescale > 0)
2208                         permutation |= SHADERPERMUTATION_DIFFUSE;
2209                 if (specularscale > 0)
2210                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2211                 if (r_refdef.fogenabled)
2212                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2213                 if (rsurface.texture->colormapping)
2214                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2215                 if (r_shadow_usingshadowmap2d)
2216                 {
2217                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2218                         if(r_shadow_shadowmapvsdct)
2219                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2220
2221                         if (r_shadow_shadowmap2ddepthbuffer)
2222                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2223                 }
2224                 if (rsurface.texture->reflectmasktexture)
2225                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2226                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2227                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2228                 if (vid.allowalphatocoverage)
2229                         GL_AlphaToCoverage(false);
2230         }
2231         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2232         {
2233                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2234                 {
2235                         switch(rsurface.texture->offsetmapping)
2236                         {
2237                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2238                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2239                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2240                         case OFFSETMAPPING_OFF: break;
2241                         }
2242                 }
2243                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2244                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2245                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2246                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2247                 // unshaded geometry (fullbright or ambient model lighting)
2248                 mode = SHADERMODE_FLATCOLOR;
2249                 ambientscale = diffusescale = specularscale = 0;
2250                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2251                         permutation |= SHADERPERMUTATION_GLOW;
2252                 if (r_refdef.fogenabled)
2253                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2254                 if (rsurface.texture->colormapping)
2255                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2256                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2257                 {
2258                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2259                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2260
2261                         if (r_shadow_shadowmap2ddepthbuffer)
2262                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2263                 }
2264                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2265                         permutation |= SHADERPERMUTATION_REFLECTION;
2266                 if (rsurface.texture->reflectmasktexture)
2267                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2268                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2269                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2270                 // when using alphatocoverage, we don't need alphakill
2271                 if (vid.allowalphatocoverage)
2272                 {
2273                         if (r_transparent_alphatocoverage.integer)
2274                         {
2275                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2276                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2277                         }
2278                         else
2279                                 GL_AlphaToCoverage(false);
2280                 }
2281         }
2282         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2283         {
2284                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2285                 {
2286                         switch(rsurface.texture->offsetmapping)
2287                         {
2288                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2289                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2290                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2291                         case OFFSETMAPPING_OFF: break;
2292                         }
2293                 }
2294                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2295                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2296                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2297                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2298                 // directional model lighting
2299                 mode = SHADERMODE_LIGHTDIRECTION;
2300                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2301                         permutation |= SHADERPERMUTATION_GLOW;
2302                 permutation |= SHADERPERMUTATION_DIFFUSE;
2303                 if (specularscale > 0)
2304                         permutation |= SHADERPERMUTATION_SPECULAR;
2305                 if (r_refdef.fogenabled)
2306                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2307                 if (rsurface.texture->colormapping)
2308                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2309                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2310                 {
2311                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2312                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2313
2314                         if (r_shadow_shadowmap2ddepthbuffer)
2315                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2316                 }
2317                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2318                         permutation |= SHADERPERMUTATION_REFLECTION;
2319                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2320                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2321                 if (rsurface.texture->reflectmasktexture)
2322                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2323                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2324                 {
2325                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2326                         if (r_shadow_bouncegriddirectional)
2327                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2328                 }
2329                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2330                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2331                 // when using alphatocoverage, we don't need alphakill
2332                 if (vid.allowalphatocoverage)
2333                 {
2334                         if (r_transparent_alphatocoverage.integer)
2335                         {
2336                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2337                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2338                         }
2339                         else
2340                                 GL_AlphaToCoverage(false);
2341                 }
2342         }
2343         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2344         {
2345                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2346                 {
2347                         switch(rsurface.texture->offsetmapping)
2348                         {
2349                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2350                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2351                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2352                         case OFFSETMAPPING_OFF: break;
2353                         }
2354                 }
2355                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2356                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2357                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2358                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2359                 // ambient model lighting
2360                 mode = SHADERMODE_LIGHTDIRECTION;
2361                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2362                         permutation |= SHADERPERMUTATION_GLOW;
2363                 if (r_refdef.fogenabled)
2364                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2365                 if (rsurface.texture->colormapping)
2366                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2367                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2368                 {
2369                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2370                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2371
2372                         if (r_shadow_shadowmap2ddepthbuffer)
2373                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2374                 }
2375                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376                         permutation |= SHADERPERMUTATION_REFLECTION;
2377                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2378                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2379                 if (rsurface.texture->reflectmasktexture)
2380                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2381                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2382                 {
2383                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2384                         if (r_shadow_bouncegriddirectional)
2385                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2386                 }
2387                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2388                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2389                 // when using alphatocoverage, we don't need alphakill
2390                 if (vid.allowalphatocoverage)
2391                 {
2392                         if (r_transparent_alphatocoverage.integer)
2393                         {
2394                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2395                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2396                         }
2397                         else
2398                                 GL_AlphaToCoverage(false);
2399                 }
2400         }
2401         else
2402         {
2403                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2404                 {
2405                         switch(rsurface.texture->offsetmapping)
2406                         {
2407                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2408                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2409                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2410                         case OFFSETMAPPING_OFF: break;
2411                         }
2412                 }
2413                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2414                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2415                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2416                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2417                 // lightmapped wall
2418                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2419                         permutation |= SHADERPERMUTATION_GLOW;
2420                 if (r_refdef.fogenabled)
2421                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2422                 if (rsurface.texture->colormapping)
2423                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2424                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2425                 {
2426                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2427                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2428
2429                         if (r_shadow_shadowmap2ddepthbuffer)
2430                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2431                 }
2432                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2433                         permutation |= SHADERPERMUTATION_REFLECTION;
2434                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2435                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2436                 if (rsurface.texture->reflectmasktexture)
2437                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2438                 if (FAKELIGHT_ENABLED)
2439                 {
2440                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2441                         mode = SHADERMODE_FAKELIGHT;
2442                         permutation |= SHADERPERMUTATION_DIFFUSE;
2443                         if (specularscale > 0)
2444                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2445                 }
2446                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2447                 {
2448                         // deluxemapping (light direction texture)
2449                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2450                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2451                         else
2452                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2453                         permutation |= SHADERPERMUTATION_DIFFUSE;
2454                         if (specularscale > 0)
2455                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2456                 }
2457                 else if (r_glsl_deluxemapping.integer >= 2)
2458                 {
2459                         // fake deluxemapping (uniform light direction in tangentspace)
2460                         if (rsurface.uselightmaptexture)
2461                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2462                         else
2463                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2464                         permutation |= SHADERPERMUTATION_DIFFUSE;
2465                         if (specularscale > 0)
2466                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2467                 }
2468                 else if (rsurface.uselightmaptexture)
2469                 {
2470                         // ordinary lightmapping (q1bsp, q3bsp)
2471                         mode = SHADERMODE_LIGHTMAP;
2472                 }
2473                 else
2474                 {
2475                         // ordinary vertex coloring (q3bsp)
2476                         mode = SHADERMODE_VERTEXCOLOR;
2477                 }
2478                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2479                 {
2480                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2481                         if (r_shadow_bouncegriddirectional)
2482                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2483                 }
2484                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2485                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2486                 // when using alphatocoverage, we don't need alphakill
2487                 if (vid.allowalphatocoverage)
2488                 {
2489                         if (r_transparent_alphatocoverage.integer)
2490                         {
2491                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2492                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2493                         }
2494                         else
2495                                 GL_AlphaToCoverage(false);
2496                 }
2497         }
2498         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2499                 colormod = dummy_colormod;
2500         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2501                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2502         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2503                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2504         switch(vid.renderpath)
2505         {
2506         case RENDERPATH_D3D9:
2507 #ifdef SUPPORTD3D
2508                 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);
2509                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2510                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2511                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2512                 if (mode == SHADERMODE_LIGHTSOURCE)
2513                 {
2514                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2515                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2516                 }
2517                 else
2518                 {
2519                         if (mode == SHADERMODE_LIGHTDIRECTION)
2520                         {
2521                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2522                         }
2523                 }
2524                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2525                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2526                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2527                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2528                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2529
2530                 if (mode == SHADERMODE_LIGHTSOURCE)
2531                 {
2532                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2533                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2534                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2536                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2537
2538                         // additive passes are only darkened by fog, not tinted
2539                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2540                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2541                 }
2542                 else
2543                 {
2544                         if (mode == SHADERMODE_FLATCOLOR)
2545                         {
2546                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2547                         }
2548                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2549                         {
2550                                 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]);
2551                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2552                                 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);
2553                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2556                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2557                         }
2558                         else
2559                         {
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2562                                 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);
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2565                         }
2566                         // additive passes are only darkened by fog, not tinted
2567                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2569                         else
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2571                         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);
2572                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2573                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2574                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2575                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2576                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2577                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2578                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2579                         if (mode == SHADERMODE_WATER)
2580                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2581                 }
2582                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2583                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2584                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2585                 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));
2586                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2587                 if (rsurface.texture->pantstexture)
2588                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2589                 else
2590                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2591                 if (rsurface.texture->shirttexture)
2592                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2593                 else
2594                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2595                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2596                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2597                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2598                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2599                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2600                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2601                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2602                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2603                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2604                         );
2605                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2606                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2607                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2608                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2609
2610                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2611                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2612                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2613                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2614                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2615                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2616                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2617                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2618                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2619                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2620                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2621                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2622                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2623                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2624                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2625                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2626                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2627                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2628                 {
2629                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2630                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2631                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2632                 }
2633                 else
2634                 {
2635                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2636                 }
2637 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2638                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2639                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2640                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2641                 {
2642                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2643                         if (rsurface.rtlight)
2644                         {
2645                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2646                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2647                         }
2648                 }
2649 #endif
2650                 break;
2651         case RENDERPATH_D3D10:
2652                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2653                 break;
2654         case RENDERPATH_D3D11:
2655                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2656                 break;
2657         case RENDERPATH_GL20:
2658         case RENDERPATH_GLES2:
2659                 if (!vid.useinterleavedarrays)
2660                 {
2661                         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);
2662                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2663                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2664                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2665                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2666                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2667                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2668                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2669                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2670                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2671                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2672                 }
2673                 else
2674                 {
2675                         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);
2676                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2677                 }
2678                 // this has to be after RSurf_PrepareVerticesForBatch
2679                 if (rsurface.batchskeletaltransform3x4)
2680                         permutation |= SHADERPERMUTATION_SKELETAL;
2681                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2682                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2683                 if (mode == SHADERMODE_LIGHTSOURCE)
2684                 {
2685                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2686                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2687                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2688                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2689                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2690                         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);
2691         
2692                         // additive passes are only darkened by fog, not tinted
2693                         if (r_glsl_permutation->loc_FogColor >= 0)
2694                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2695                         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);
2696                 }
2697                 else
2698                 {
2699                         if (mode == SHADERMODE_FLATCOLOR)
2700                         {
2701                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2702                         }
2703                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2704                         {
2705                                 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]);
2706                                 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]);
2707                                 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);
2708                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2709                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2710                                 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]);
2711                                 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]);
2712                         }
2713                         else
2714                         {
2715                                 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]);
2716                                 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]);
2717                                 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);
2718                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2719                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2720                         }
2721                         // additive passes are only darkened by fog, not tinted
2722                         if (r_glsl_permutation->loc_FogColor >= 0)
2723                         {
2724                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2725                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2726                                 else
2727                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2728                         }
2729                         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);
2730                         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]);
2731                         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]);
2732                         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]);
2733                         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]);
2734                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2735                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2736                         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);
2737                         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]);
2738                 }
2739                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2740                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2741                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2742                 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]);
2743                 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]);
2744
2745                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2746                 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));
2747                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2748                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2749                 {
2750                         if (rsurface.texture->pantstexture)
2751                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2752                         else
2753                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2754                 }
2755                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2756                 {
2757                         if (rsurface.texture->shirttexture)
2758                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2759                         else
2760                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2761                 }
2762                 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]);
2763                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2764                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2765                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2766                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2767                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2768                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2769                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2770                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2771                         );
2772                 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);
2773                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2774                 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]);
2775                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2776                 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);}
2777                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2778
2779                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2780                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2781                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2782                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2783                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2784                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2785                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2786                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2787                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2788                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2789                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2790                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2791                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2792                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2793                 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);
2794                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2795                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2796                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2797                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2798                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2799                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2800                 {
2801                         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);
2802                         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);
2803                         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);
2804                 }
2805                 else
2806                 {
2807                         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);
2808                 }
2809                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2810                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2811                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2812                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2813                 {
2814                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2815                         if (rsurface.rtlight)
2816                         {
2817                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2818                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2819                         }
2820                 }
2821                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2822                 if (r_glsl_permutation->loc_Skeletal_Transform12 >= 0 && rsurface.batchskeletalnumtransforms > 0)
2823                         qglUniform4fv(r_glsl_permutation->loc_Skeletal_Transform12, rsurface.batchskeletalnumtransforms*3, rsurface.batchskeletaltransform3x4);
2824                 CHECKGLERROR
2825                 break;
2826         case RENDERPATH_GL11:
2827         case RENDERPATH_GL13:
2828         case RENDERPATH_GLES1:
2829                 break;
2830         case RENDERPATH_SOFT:
2831                 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);
2832                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2833                 R_SetupShader_SetPermutationSoft(mode, permutation);
2834                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2835                 if (mode == SHADERMODE_LIGHTSOURCE)
2836                 {
2837                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2838                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2839                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2840                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2841                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2842                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2843         
2844                         // additive passes are only darkened by fog, not tinted
2845                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2846                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2847                 }
2848                 else
2849                 {
2850                         if (mode == SHADERMODE_FLATCOLOR)
2851                         {
2852                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2853                         }
2854                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2855                         {
2856                                 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]);
2857                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2858                                 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);
2859                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2860                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2861                                 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]);
2862                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2863                         }
2864                         else
2865                         {
2866                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2867                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2868                                 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);
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2871                         }
2872                         // additive passes are only darkened by fog, not tinted
2873                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2875                         else
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2877                         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);
2878                         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]);
2879                         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]);
2880                         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]);
2881                         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]);
2882                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2883                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2884                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2885                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2886                 }
2887                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2888                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2889                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2890                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2891                 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]);
2892
2893                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2894                 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));
2895                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2896                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2897                 {
2898                         if (rsurface.texture->pantstexture)
2899                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2900                         else
2901                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2902                 }
2903                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2904                 {
2905                         if (rsurface.texture->shirttexture)
2906                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2907                         else
2908                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2909                 }
2910                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2911                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2912                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2913                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2914                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2915                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2916                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2917                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2918                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2919                         );
2920                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2921                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2922                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2923                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2924
2925                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2926                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2927                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2928                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2929                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2930                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2931                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2932                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2933                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2934                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2935                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2936                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2937                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2938                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2939                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2940                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2941                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2942                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2943                 {
2944                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2945                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2946                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2947                 }
2948                 else
2949                 {
2950                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2951                 }
2952 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2953                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2954                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2955                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2956                 {
2957                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2958                         if (rsurface.rtlight)
2959                         {
2960                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2961                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2962                         }
2963                 }
2964                 break;
2965         }
2966 }
2967
2968 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2969 {
2970         // select a permutation of the lighting shader appropriate to this
2971         // combination of texture, entity, light source, and fogging, only use the
2972         // minimum features necessary to avoid wasting rendering time in the
2973         // fragment shader on features that are not being used
2974         unsigned int permutation = 0;
2975         unsigned int mode = 0;
2976         const float *lightcolorbase = rtlight->currentcolor;
2977         float ambientscale = rtlight->ambientscale;
2978         float diffusescale = rtlight->diffusescale;
2979         float specularscale = rtlight->specularscale;
2980         // this is the location of the light in view space
2981         vec3_t viewlightorigin;
2982         // this transforms from view space (camera) to light space (cubemap)
2983         matrix4x4_t viewtolight;
2984         matrix4x4_t lighttoview;
2985         float viewtolight16f[16];
2986         // light source
2987         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2988         if (rtlight->currentcubemap != r_texture_whitecube)
2989                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2990         if (diffusescale > 0)
2991                 permutation |= SHADERPERMUTATION_DIFFUSE;
2992         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2993                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2994         if (r_shadow_usingshadowmap2d)
2995         {
2996                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2997                 if (r_shadow_shadowmapvsdct)
2998                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2999
3000                 if (r_shadow_shadowmap2ddepthbuffer)
3001                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3002         }
3003         if (vid.allowalphatocoverage)
3004                 GL_AlphaToCoverage(false);
3005         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3006         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3007         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3008         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3009         switch(vid.renderpath)
3010         {
3011         case RENDERPATH_D3D9:
3012 #ifdef SUPPORTD3D
3013                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3014                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3015                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3016                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3017                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3018                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3019                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3020                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3021                 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);
3022                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3023                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3024
3025                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3026                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3027                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3028                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3029                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3030 #endif
3031                 break;
3032         case RENDERPATH_D3D10:
3033                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3034                 break;
3035         case RENDERPATH_D3D11:
3036                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3037                 break;
3038         case RENDERPATH_GL20:
3039         case RENDERPATH_GLES2:
3040                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3041                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3042                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3043                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3044                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3045                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3046                 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]);
3047                 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]);
3048                 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);
3049                 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]);
3050                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3051
3052                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3053                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3054                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3055                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3056                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3057                 break;
3058         case RENDERPATH_GL11:
3059         case RENDERPATH_GL13:
3060         case RENDERPATH_GLES1:
3061                 break;
3062         case RENDERPATH_SOFT:
3063                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3064                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3065                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3066                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3067                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3068                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3069                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3070                 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]);
3071                 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);
3072                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3073                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3074
3075                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3076                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3077                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3078                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3079                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3080                 break;
3081         }
3082 }
3083
3084 #define SKINFRAME_HASH 1024
3085
3086 typedef struct
3087 {
3088         int loadsequence; // incremented each level change
3089         memexpandablearray_t array;
3090         skinframe_t *hash[SKINFRAME_HASH];
3091 }
3092 r_skinframe_t;
3093 r_skinframe_t r_skinframe;
3094
3095 void R_SkinFrame_PrepareForPurge(void)
3096 {
3097         r_skinframe.loadsequence++;
3098         // wrap it without hitting zero
3099         if (r_skinframe.loadsequence >= 200)
3100                 r_skinframe.loadsequence = 1;
3101 }
3102
3103 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3104 {
3105         if (!skinframe)
3106                 return;
3107         // mark the skinframe as used for the purging code
3108         skinframe->loadsequence = r_skinframe.loadsequence;
3109 }
3110
3111 void R_SkinFrame_Purge(void)
3112 {
3113         int i;
3114         skinframe_t *s;
3115         for (i = 0;i < SKINFRAME_HASH;i++)
3116         {
3117                 for (s = r_skinframe.hash[i];s;s = s->next)
3118                 {
3119                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3120                         {
3121                                 if (s->merged == s->base)
3122                                         s->merged = NULL;
3123                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3124                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3125                                 R_PurgeTexture(s->merged);s->merged = NULL;
3126                                 R_PurgeTexture(s->base  );s->base   = NULL;
3127                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3128                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3129                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3130                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3131                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3132                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3133                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3134                                 s->loadsequence = 0;
3135                         }
3136                 }
3137         }
3138 }
3139
3140 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3141         skinframe_t *item;
3142         char basename[MAX_QPATH];
3143
3144         Image_StripImageExtension(name, basename, sizeof(basename));
3145
3146         if( last == NULL ) {
3147                 int hashindex;
3148                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3149                 item = r_skinframe.hash[hashindex];
3150         } else {
3151                 item = last->next;
3152         }
3153
3154         // linearly search through the hash bucket
3155         for( ; item ; item = item->next ) {
3156                 if( !strcmp( item->basename, basename ) ) {
3157                         return item;
3158                 }
3159         }
3160         return NULL;
3161 }
3162
3163 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3164 {
3165         skinframe_t *item;
3166         int hashindex;
3167         char basename[MAX_QPATH];
3168
3169         Image_StripImageExtension(name, basename, sizeof(basename));
3170
3171         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3172         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3173                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3174                         break;
3175
3176         if (!item) {
3177                 rtexture_t *dyntexture;
3178                 // check whether its a dynamic texture
3179                 dyntexture = CL_GetDynTexture( basename );
3180                 if (!add && !dyntexture)
3181                         return NULL;
3182                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3183                 memset(item, 0, sizeof(*item));
3184                 strlcpy(item->basename, basename, sizeof(item->basename));
3185                 item->base = dyntexture; // either NULL or dyntexture handle
3186                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3187                 item->comparewidth = comparewidth;
3188                 item->compareheight = compareheight;
3189                 item->comparecrc = comparecrc;
3190                 item->next = r_skinframe.hash[hashindex];
3191                 r_skinframe.hash[hashindex] = item;
3192         }
3193         else if (textureflags & TEXF_FORCE_RELOAD)
3194         {
3195                 rtexture_t *dyntexture;
3196                 // check whether its a dynamic texture
3197                 dyntexture = CL_GetDynTexture( basename );
3198                 if (!add && !dyntexture)
3199                         return NULL;
3200                 if (item->merged == item->base)
3201                         item->merged = NULL;
3202                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3203                 R_PurgeTexture(item->stain );item->stain  = NULL;
3204                 R_PurgeTexture(item->merged);item->merged = NULL;
3205                 R_PurgeTexture(item->base  );item->base   = NULL;
3206                 R_PurgeTexture(item->pants );item->pants  = NULL;
3207                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3208                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3209                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3210                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3211                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3212         R_PurgeTexture(item->reflect);item->reflect = NULL;
3213                 item->loadsequence = 0;
3214         }
3215         else if( item->base == NULL )
3216         {
3217                 rtexture_t *dyntexture;
3218                 // check whether its a dynamic texture
3219                 // 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]
3220                 dyntexture = CL_GetDynTexture( basename );
3221                 item->base = dyntexture; // either NULL or dyntexture handle
3222         }
3223
3224         R_SkinFrame_MarkUsed(item);
3225         return item;
3226 }
3227
3228 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3229         { \
3230                 unsigned long long avgcolor[5], wsum; \
3231                 int pix, comp, w; \
3232                 avgcolor[0] = 0; \
3233                 avgcolor[1] = 0; \
3234                 avgcolor[2] = 0; \
3235                 avgcolor[3] = 0; \
3236                 avgcolor[4] = 0; \
3237                 wsum = 0; \
3238                 for(pix = 0; pix < cnt; ++pix) \
3239                 { \
3240                         w = 0; \
3241                         for(comp = 0; comp < 3; ++comp) \
3242                                 w += getpixel; \
3243                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3244                         { \
3245                                 ++wsum; \
3246                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3247                                 w = getpixel; \
3248                                 for(comp = 0; comp < 3; ++comp) \
3249                                         avgcolor[comp] += getpixel * w; \
3250                                 avgcolor[3] += w; \
3251                         } \
3252                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3253                         avgcolor[4] += getpixel; \
3254                 } \
3255                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3256                         avgcolor[3] = 1; \
3257                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3258                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3259                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3260                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3261         }
3262
3263 extern cvar_t gl_picmip;
3264 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3265 {
3266         int j;
3267         unsigned char *pixels;
3268         unsigned char *bumppixels;
3269         unsigned char *basepixels = NULL;
3270         int basepixels_width = 0;
3271         int basepixels_height = 0;
3272         skinframe_t *skinframe;
3273         rtexture_t *ddsbase = NULL;
3274         qboolean ddshasalpha = false;
3275         float ddsavgcolor[4];
3276         char basename[MAX_QPATH];
3277         int miplevel = R_PicmipForFlags(textureflags);
3278         int savemiplevel = miplevel;
3279         int mymiplevel;
3280         char vabuf[1024];
3281
3282         if (cls.state == ca_dedicated)
3283                 return NULL;
3284
3285         // return an existing skinframe if already loaded
3286         // if loading of the first image fails, don't make a new skinframe as it
3287         // would cause all future lookups of this to be missing
3288         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3289         if (skinframe && skinframe->base)
3290                 return skinframe;
3291
3292         Image_StripImageExtension(name, basename, sizeof(basename));
3293
3294         // check for DDS texture file first
3295         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3296         {
3297                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3298                 if (basepixels == NULL)
3299                         return NULL;
3300         }
3301
3302         // FIXME handle miplevel
3303
3304         if (developer_loading.integer)
3305                 Con_Printf("loading skin \"%s\"\n", name);
3306
3307         // we've got some pixels to store, so really allocate this new texture now
3308         if (!skinframe)
3309                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3310         textureflags &= ~TEXF_FORCE_RELOAD;
3311         skinframe->stain = NULL;
3312         skinframe->merged = NULL;
3313         skinframe->base = NULL;
3314         skinframe->pants = NULL;
3315         skinframe->shirt = NULL;
3316         skinframe->nmap = NULL;
3317         skinframe->gloss = NULL;
3318         skinframe->glow = NULL;
3319         skinframe->fog = NULL;
3320         skinframe->reflect = NULL;
3321         skinframe->hasalpha = false;
3322
3323         if (ddsbase)
3324         {
3325                 skinframe->base = ddsbase;
3326                 skinframe->hasalpha = ddshasalpha;
3327                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3328                 if (r_loadfog && skinframe->hasalpha)
3329                         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);
3330                 //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]);
3331         }
3332         else
3333         {
3334                 basepixels_width = image_width;
3335                 basepixels_height = image_height;
3336                 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);
3337                 if (textureflags & TEXF_ALPHA)
3338                 {
3339                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3340                         {
3341                                 if (basepixels[j] < 255)
3342                                 {
3343                                         skinframe->hasalpha = true;
3344                                         break;
3345                                 }
3346                         }
3347                         if (r_loadfog && skinframe->hasalpha)
3348                         {
3349                                 // has transparent pixels
3350                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3351                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3352                                 {
3353                                         pixels[j+0] = 255;
3354                                         pixels[j+1] = 255;
3355                                         pixels[j+2] = 255;
3356                                         pixels[j+3] = basepixels[j+3];
3357                                 }
3358                                 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);
3359                                 Mem_Free(pixels);
3360                         }
3361                 }
3362                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3363 #ifndef USE_GLES2
3364                 //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]);
3365                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3366                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3367                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3368                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3369 #endif
3370         }
3371
3372         if (r_loaddds)
3373         {
3374                 mymiplevel = savemiplevel;
3375                 if (r_loadnormalmap)
3376                         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);
3377                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3378                 if (r_loadgloss)
3379                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3380                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3381                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3382                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3383         }
3384
3385         // _norm is the name used by tenebrae and has been adopted as standard
3386         if (r_loadnormalmap && skinframe->nmap == NULL)
3387         {
3388                 mymiplevel = savemiplevel;
3389                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3390                 {
3391                         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);
3392                         Mem_Free(pixels);
3393                         pixels = NULL;
3394                 }
3395                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3396                 {
3397                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3398                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3399                         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);
3400                         Mem_Free(pixels);
3401                         Mem_Free(bumppixels);
3402                 }
3403                 else if (r_shadow_bumpscale_basetexture.value > 0)
3404                 {
3405                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3406                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3407                         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);
3408                         Mem_Free(pixels);
3409                 }
3410 #ifndef USE_GLES2
3411                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3412                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3413 #endif
3414         }
3415
3416         // _luma is supported only for tenebrae compatibility
3417         // _glow is the preferred name
3418         mymiplevel = savemiplevel;
3419         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))))
3420         {
3421                 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);
3422 #ifndef USE_GLES2
3423                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3424                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3425 #endif
3426                 Mem_Free(pixels);pixels = NULL;
3427         }
3428
3429         mymiplevel = savemiplevel;
3430         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3431         {
3432                 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);
3433 #ifndef USE_GLES2
3434                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3435                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3436 #endif
3437                 Mem_Free(pixels);
3438                 pixels = NULL;
3439         }
3440
3441         mymiplevel = savemiplevel;
3442         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3443         {
3444                 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);
3445 #ifndef USE_GLES2
3446                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3447                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3448 #endif
3449                 Mem_Free(pixels);
3450                 pixels = NULL;
3451         }
3452
3453         mymiplevel = savemiplevel;
3454         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3455         {
3456                 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);
3457 #ifndef USE_GLES2
3458                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3459                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3460 #endif
3461                 Mem_Free(pixels);
3462                 pixels = NULL;
3463         }
3464
3465         mymiplevel = savemiplevel;
3466         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3467         {
3468                 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);
3469 #ifndef USE_GLES2
3470                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3471                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3472 #endif
3473                 Mem_Free(pixels);
3474                 pixels = NULL;
3475         }
3476
3477         if (basepixels)
3478                 Mem_Free(basepixels);
3479
3480         return skinframe;
3481 }
3482
3483 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3484 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3485 {
3486         int i;
3487         unsigned char *temp1, *temp2;
3488         skinframe_t *skinframe;
3489         char vabuf[1024];
3490
3491         if (cls.state == ca_dedicated)
3492                 return NULL;
3493
3494         // if already loaded just return it, otherwise make a new skinframe
3495         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3496         if (skinframe->base)
3497                 return skinframe;
3498         textureflags &= ~TEXF_FORCE_RELOAD;
3499
3500         skinframe->stain = NULL;
3501         skinframe->merged = NULL;
3502         skinframe->base = NULL;
3503         skinframe->pants = NULL;
3504         skinframe->shirt = NULL;
3505         skinframe->nmap = NULL;
3506         skinframe->gloss = NULL;
3507         skinframe->glow = NULL;
3508         skinframe->fog = NULL;
3509         skinframe->reflect = NULL;
3510         skinframe->hasalpha = false;
3511
3512         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3513         if (!skindata)
3514                 return NULL;
3515
3516         if (developer_loading.integer)
3517                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3518
3519         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3520         {
3521                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3522                 temp2 = temp1 + width * height * 4;
3523                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3524                 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);
3525                 Mem_Free(temp1);
3526         }
3527         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3528         if (textureflags & TEXF_ALPHA)
3529         {
3530                 for (i = 3;i < width * height * 4;i += 4)
3531                 {
3532                         if (skindata[i] < 255)
3533                         {
3534                                 skinframe->hasalpha = true;
3535                                 break;
3536                         }
3537                 }
3538                 if (r_loadfog && skinframe->hasalpha)
3539                 {
3540                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3541                         memcpy(fogpixels, skindata, width * height * 4);
3542                         for (i = 0;i < width * height * 4;i += 4)
3543                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3544                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3545                         Mem_Free(fogpixels);
3546                 }
3547         }
3548
3549         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3550         //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]);
3551
3552         return skinframe;
3553 }
3554
3555 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3556 {
3557         int i;
3558         int featuresmask;
3559         skinframe_t *skinframe;
3560
3561         if (cls.state == ca_dedicated)
3562                 return NULL;
3563
3564         // if already loaded just return it, otherwise make a new skinframe
3565         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3566         if (skinframe->base)
3567                 return skinframe;
3568         //textureflags &= ~TEXF_FORCE_RELOAD;
3569
3570         skinframe->stain = NULL;
3571         skinframe->merged = NULL;
3572         skinframe->base = NULL;
3573         skinframe->pants = NULL;
3574         skinframe->shirt = NULL;
3575         skinframe->nmap = NULL;
3576         skinframe->gloss = NULL;
3577         skinframe->glow = NULL;
3578         skinframe->fog = NULL;
3579         skinframe->reflect = NULL;
3580         skinframe->hasalpha = false;
3581
3582         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3583         if (!skindata)
3584                 return NULL;
3585
3586         if (developer_loading.integer)
3587                 Con_Printf("loading quake skin \"%s\"\n", name);
3588
3589         // 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)
3590         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3591         memcpy(skinframe->qpixels, skindata, width*height);
3592         skinframe->qwidth = width;
3593         skinframe->qheight = height;
3594
3595         featuresmask = 0;
3596         for (i = 0;i < width * height;i++)
3597                 featuresmask |= palette_featureflags[skindata[i]];
3598
3599         skinframe->hasalpha = false;
3600         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3601         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3602         skinframe->qgeneratemerged = true;
3603         skinframe->qgeneratebase = skinframe->qhascolormapping;
3604         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3605
3606         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3607         //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]);
3608
3609         return skinframe;
3610 }
3611
3612 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3613 {
3614         int width;
3615         int height;
3616         unsigned char *skindata;
3617         char vabuf[1024];
3618
3619         if (!skinframe->qpixels)
3620                 return;
3621
3622         if (!skinframe->qhascolormapping)
3623                 colormapped = false;
3624
3625         if (colormapped)
3626         {
3627                 if (!skinframe->qgeneratebase)
3628                         return;
3629         }
3630         else
3631         {
3632                 if (!skinframe->qgeneratemerged)
3633                         return;
3634         }
3635
3636         width = skinframe->qwidth;
3637         height = skinframe->qheight;
3638         skindata = skinframe->qpixels;
3639
3640         if (skinframe->qgeneratenmap)
3641         {
3642                 unsigned char *temp1, *temp2;
3643                 skinframe->qgeneratenmap = false;
3644                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3645                 temp2 = temp1 + width * height * 4;
3646                 // use either a custom palette or the quake palette
3647                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3648                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3649                 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);
3650                 Mem_Free(temp1);
3651         }
3652
3653         if (skinframe->qgenerateglow)
3654         {
3655                 skinframe->qgenerateglow = false;
3656                 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
3657         }
3658
3659         if (colormapped)
3660         {
3661                 skinframe->qgeneratebase = false;
3662                 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);
3663                 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);
3664                 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);
3665         }
3666         else
3667         {
3668                 skinframe->qgeneratemerged = false;
3669                 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);
3670         }
3671
3672         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3673         {
3674                 Mem_Free(skinframe->qpixels);
3675                 skinframe->qpixels = NULL;
3676         }
3677 }
3678
3679 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)
3680 {
3681         int i;
3682         skinframe_t *skinframe;
3683         char vabuf[1024];
3684
3685         if (cls.state == ca_dedicated)
3686                 return NULL;
3687
3688         // if already loaded just return it, otherwise make a new skinframe
3689         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3690         if (skinframe->base)
3691                 return skinframe;
3692         textureflags &= ~TEXF_FORCE_RELOAD;
3693
3694         skinframe->stain = NULL;
3695         skinframe->merged = NULL;
3696         skinframe->base = NULL;
3697         skinframe->pants = NULL;
3698         skinframe->shirt = NULL;
3699         skinframe->nmap = NULL;
3700         skinframe->gloss = NULL;
3701         skinframe->glow = NULL;
3702         skinframe->fog = NULL;
3703         skinframe->reflect = NULL;
3704         skinframe->hasalpha = false;
3705
3706         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3707         if (!skindata)
3708                 return NULL;
3709
3710         if (developer_loading.integer)
3711                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3712
3713         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3714         if (textureflags & TEXF_ALPHA)
3715         {
3716                 for (i = 0;i < width * height;i++)
3717                 {
3718                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3719                         {
3720                                 skinframe->hasalpha = true;
3721                                 break;
3722                         }
3723                 }
3724                 if (r_loadfog && skinframe->hasalpha)
3725                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3726         }
3727
3728         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3729         //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]);
3730
3731         return skinframe;
3732 }
3733
3734 skinframe_t *R_SkinFrame_LoadMissing(void)
3735 {
3736         skinframe_t *skinframe;
3737
3738         if (cls.state == ca_dedicated)
3739                 return NULL;
3740
3741         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3742         skinframe->stain = NULL;
3743         skinframe->merged = NULL;
3744         skinframe->base = NULL;
3745         skinframe->pants = NULL;
3746         skinframe->shirt = NULL;
3747         skinframe->nmap = NULL;
3748         skinframe->gloss = NULL;
3749         skinframe->glow = NULL;
3750         skinframe->fog = NULL;
3751         skinframe->reflect = NULL;
3752         skinframe->hasalpha = false;
3753
3754         skinframe->avgcolor[0] = rand() / RAND_MAX;
3755         skinframe->avgcolor[1] = rand() / RAND_MAX;
3756         skinframe->avgcolor[2] = rand() / RAND_MAX;
3757         skinframe->avgcolor[3] = 1;
3758
3759         return skinframe;
3760 }
3761
3762 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3763 typedef struct suffixinfo_s
3764 {
3765         const char *suffix;
3766         qboolean flipx, flipy, flipdiagonal;
3767 }
3768 suffixinfo_t;
3769 static suffixinfo_t suffix[3][6] =
3770 {
3771         {
3772                 {"px",   false, false, false},
3773                 {"nx",   false, false, false},
3774                 {"py",   false, false, false},
3775                 {"ny",   false, false, false},
3776                 {"pz",   false, false, false},
3777                 {"nz",   false, false, false}
3778         },
3779         {
3780                 {"posx", false, false, false},
3781                 {"negx", false, false, false},
3782                 {"posy", false, false, false},
3783                 {"negy", false, false, false},
3784                 {"posz", false, false, false},
3785                 {"negz", false, false, false}
3786         },
3787         {
3788                 {"rt",    true, false,  true},
3789                 {"lf",   false,  true,  true},
3790                 {"ft",    true,  true, false},
3791                 {"bk",   false, false, false},
3792                 {"up",    true, false,  true},
3793                 {"dn",    true, false,  true}
3794         }
3795 };
3796
3797 static int componentorder[4] = {0, 1, 2, 3};
3798
3799 static rtexture_t *R_LoadCubemap(const char *basename)
3800 {
3801         int i, j, cubemapsize;
3802         unsigned char *cubemappixels, *image_buffer;
3803         rtexture_t *cubemaptexture;
3804         char name[256];
3805         // must start 0 so the first loadimagepixels has no requested width/height
3806         cubemapsize = 0;
3807         cubemappixels = NULL;
3808         cubemaptexture = NULL;
3809         // keep trying different suffix groups (posx, px, rt) until one loads
3810         for (j = 0;j < 3 && !cubemappixels;j++)
3811         {
3812                 // load the 6 images in the suffix group
3813                 for (i = 0;i < 6;i++)
3814                 {
3815                         // generate an image name based on the base and and suffix
3816                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3817                         // load it
3818                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3819                         {
3820                                 // an image loaded, make sure width and height are equal
3821                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3822                                 {
3823                                         // if this is the first image to load successfully, allocate the cubemap memory
3824                                         if (!cubemappixels && image_width >= 1)
3825                                         {
3826                                                 cubemapsize = image_width;
3827                                                 // note this clears to black, so unavailable sides are black
3828                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3829                                         }
3830                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3831                                         if (cubemappixels)
3832                                                 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);
3833                                 }
3834                                 else
3835                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3836                                 // free the image
3837                                 Mem_Free(image_buffer);
3838                         }
3839                 }
3840         }
3841         // if a cubemap loaded, upload it
3842         if (cubemappixels)
3843         {
3844                 if (developer_loading.integer)
3845                         Con_Printf("loading cubemap \"%s\"\n", basename);
3846
3847                 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);
3848                 Mem_Free(cubemappixels);
3849         }
3850         else
3851         {
3852                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3853                 if (developer_loading.integer)
3854                 {
3855                         Con_Printf("(tried tried images ");
3856                         for (j = 0;j < 3;j++)
3857                                 for (i = 0;i < 6;i++)
3858                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3859                         Con_Print(" and was unable to find any of them).\n");
3860                 }
3861         }
3862         return cubemaptexture;
3863 }
3864
3865 rtexture_t *R_GetCubemap(const char *basename)
3866 {
3867         int i;
3868         for (i = 0;i < r_texture_numcubemaps;i++)
3869                 if (r_texture_cubemaps[i] != NULL)
3870                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3871                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3872         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3873                 return r_texture_whitecube;
3874         r_texture_numcubemaps++;
3875         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3876         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3877         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3878         return r_texture_cubemaps[i]->texture;
3879 }
3880
3881 static void R_Main_FreeViewCache(void)
3882 {
3883         if (r_refdef.viewcache.entityvisible)
3884                 Mem_Free(r_refdef.viewcache.entityvisible);
3885         if (r_refdef.viewcache.world_pvsbits)
3886                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3887         if (r_refdef.viewcache.world_leafvisible)
3888                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3889         if (r_refdef.viewcache.world_surfacevisible)
3890                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3891         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3892 }
3893
3894 static void R_Main_ResizeViewCache(void)
3895 {
3896         int numentities = r_refdef.scene.numentities;
3897         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3898         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3899         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3900         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3901         if (r_refdef.viewcache.maxentities < numentities)
3902         {
3903                 r_refdef.viewcache.maxentities = numentities;
3904                 if (r_refdef.viewcache.entityvisible)
3905                         Mem_Free(r_refdef.viewcache.entityvisible);
3906                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3907         }
3908         if (r_refdef.viewcache.world_numclusters != numclusters)
3909         {
3910                 r_refdef.viewcache.world_numclusters = numclusters;
3911                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3912                 if (r_refdef.viewcache.world_pvsbits)
3913                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3914                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3915         }
3916         if (r_refdef.viewcache.world_numleafs != numleafs)
3917         {
3918                 r_refdef.viewcache.world_numleafs = numleafs;
3919                 if (r_refdef.viewcache.world_leafvisible)
3920                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3921                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3922         }
3923         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3924         {
3925                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3926                 if (r_refdef.viewcache.world_surfacevisible)
3927                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3928                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3929         }
3930 }
3931
3932 extern rtexture_t *loadingscreentexture;
3933 static void gl_main_start(void)
3934 {
3935         loadingscreentexture = NULL;
3936         r_texture_blanknormalmap = NULL;
3937         r_texture_white = NULL;
3938         r_texture_grey128 = NULL;
3939         r_texture_black = NULL;
3940         r_texture_whitecube = NULL;
3941         r_texture_normalizationcube = NULL;
3942         r_texture_fogattenuation = NULL;
3943         r_texture_fogheighttexture = NULL;
3944         r_texture_gammaramps = NULL;
3945         r_texture_numcubemaps = 0;
3946
3947         r_loaddds = r_texture_dds_load.integer != 0;
3948         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3949
3950         switch(vid.renderpath)
3951         {
3952         case RENDERPATH_GL20:
3953         case RENDERPATH_D3D9:
3954         case RENDERPATH_D3D10:
3955         case RENDERPATH_D3D11:
3956         case RENDERPATH_SOFT:
3957         case RENDERPATH_GLES2:
3958                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3959                 Cvar_SetValueQuick(&gl_combine, 1);
3960                 Cvar_SetValueQuick(&r_glsl, 1);
3961                 r_loadnormalmap = true;
3962                 r_loadgloss = true;
3963                 r_loadfog = false;
3964                 break;
3965         case RENDERPATH_GL13:
3966         case RENDERPATH_GLES1:
3967                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3968                 Cvar_SetValueQuick(&gl_combine, 1);
3969                 Cvar_SetValueQuick(&r_glsl, 0);
3970                 r_loadnormalmap = false;
3971                 r_loadgloss = false;
3972                 r_loadfog = true;
3973                 break;
3974         case RENDERPATH_GL11:
3975                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3976                 Cvar_SetValueQuick(&gl_combine, 0);
3977                 Cvar_SetValueQuick(&r_glsl, 0);
3978                 r_loadnormalmap = false;
3979                 r_loadgloss = false;
3980                 r_loadfog = true;
3981                 break;
3982         }
3983
3984         R_AnimCache_Free();
3985         R_FrameData_Reset();
3986
3987         r_numqueries = 0;
3988         r_maxqueries = 0;
3989         memset(r_queries, 0, sizeof(r_queries));
3990
3991         r_qwskincache = NULL;
3992         r_qwskincache_size = 0;
3993
3994         // due to caching of texture_t references, the collision cache must be reset
3995         Collision_Cache_Reset(true);
3996
3997         // set up r_skinframe loading system for textures
3998         memset(&r_skinframe, 0, sizeof(r_skinframe));
3999         r_skinframe.loadsequence = 1;
4000         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4001
4002         r_main_texturepool = R_AllocTexturePool();
4003         R_BuildBlankTextures();
4004         R_BuildNoTexture();
4005         if (vid.support.arb_texture_cube_map)
4006         {
4007                 R_BuildWhiteCube();
4008                 R_BuildNormalizationCube();
4009         }
4010         r_texture_fogattenuation = NULL;
4011         r_texture_fogheighttexture = NULL;
4012         r_texture_gammaramps = NULL;
4013         //r_texture_fogintensity = NULL;
4014         memset(&r_fb, 0, sizeof(r_fb));
4015         r_glsl_permutation = NULL;
4016         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4017         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4018         glslshaderstring = NULL;
4019 #ifdef SUPPORTD3D
4020         r_hlsl_permutation = NULL;
4021         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4022         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4023 #endif
4024         hlslshaderstring = NULL;
4025         memset(&r_svbsp, 0, sizeof (r_svbsp));
4026
4027         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4028         r_texture_numcubemaps = 0;
4029
4030         r_refdef.fogmasktable_density = 0;
4031 }
4032
4033 static void gl_main_shutdown(void)
4034 {
4035         R_AnimCache_Free();
4036         R_FrameData_Reset();
4037
4038         R_Main_FreeViewCache();
4039
4040         switch(vid.renderpath)
4041         {
4042         case RENDERPATH_GL11:
4043         case RENDERPATH_GL13:
4044         case RENDERPATH_GL20:
4045         case RENDERPATH_GLES1:
4046         case RENDERPATH_GLES2:
4047 #ifdef GL_SAMPLES_PASSED_ARB
4048                 if (r_maxqueries)
4049                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4050 #endif
4051                 break;
4052         case RENDERPATH_D3D9:
4053                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4054                 break;
4055         case RENDERPATH_D3D10:
4056                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4057                 break;
4058         case RENDERPATH_D3D11:
4059                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4060                 break;
4061         case RENDERPATH_SOFT:
4062                 break;
4063         }
4064
4065         r_numqueries = 0;
4066         r_maxqueries = 0;
4067         memset(r_queries, 0, sizeof(r_queries));
4068
4069         r_qwskincache = NULL;
4070         r_qwskincache_size = 0;
4071
4072         // clear out the r_skinframe state
4073         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4074         memset(&r_skinframe, 0, sizeof(r_skinframe));
4075
4076         if (r_svbsp.nodes)
4077                 Mem_Free(r_svbsp.nodes);
4078         memset(&r_svbsp, 0, sizeof (r_svbsp));
4079         R_FreeTexturePool(&r_main_texturepool);
4080         loadingscreentexture = NULL;
4081         r_texture_blanknormalmap = NULL;
4082         r_texture_white = NULL;
4083         r_texture_grey128 = NULL;
4084         r_texture_black = NULL;
4085         r_texture_whitecube = NULL;
4086         r_texture_normalizationcube = NULL;
4087         r_texture_fogattenuation = NULL;
4088         r_texture_fogheighttexture = NULL;
4089         r_texture_gammaramps = NULL;
4090         r_texture_numcubemaps = 0;
4091         //r_texture_fogintensity = NULL;
4092         memset(&r_fb, 0, sizeof(r_fb));
4093         R_GLSL_Restart_f();
4094
4095         r_glsl_permutation = NULL;
4096         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4097         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4098         glslshaderstring = NULL;
4099 #ifdef SUPPORTD3D
4100         r_hlsl_permutation = NULL;
4101         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4102         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4103 #endif
4104         hlslshaderstring = NULL;
4105 }
4106
4107 static void gl_main_newmap(void)
4108 {
4109         // FIXME: move this code to client
4110         char *entities, entname[MAX_QPATH];
4111         if (r_qwskincache)
4112                 Mem_Free(r_qwskincache);
4113         r_qwskincache = NULL;
4114         r_qwskincache_size = 0;
4115         if (cl.worldmodel)
4116         {
4117                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4118                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4119                 {
4120                         CL_ParseEntityLump(entities);
4121                         Mem_Free(entities);
4122                         return;
4123                 }
4124                 if (cl.worldmodel->brush.entities)
4125                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4126         }
4127         R_Main_FreeViewCache();
4128
4129         R_FrameData_Reset();
4130 }
4131
4132 void GL_Main_Init(void)
4133 {
4134         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4135
4136         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4137         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4138         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4139         if (gamemode == GAME_NEHAHRA)
4140         {
4141                 Cvar_RegisterVariable (&gl_fogenable);
4142                 Cvar_RegisterVariable (&gl_fogdensity);
4143                 Cvar_RegisterVariable (&gl_fogred);
4144                 Cvar_RegisterVariable (&gl_foggreen);
4145                 Cvar_RegisterVariable (&gl_fogblue);
4146                 Cvar_RegisterVariable (&gl_fogstart);
4147                 Cvar_RegisterVariable (&gl_fogend);
4148                 Cvar_RegisterVariable (&gl_skyclip);
4149         }
4150         Cvar_RegisterVariable(&r_motionblur);
4151         Cvar_RegisterVariable(&r_damageblur);
4152         Cvar_RegisterVariable(&r_motionblur_averaging);
4153         Cvar_RegisterVariable(&r_motionblur_randomize);
4154         Cvar_RegisterVariable(&r_motionblur_minblur);
4155         Cvar_RegisterVariable(&r_motionblur_maxblur);
4156         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4157         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4158         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4159         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4160         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4161         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4162         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4163         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4164         Cvar_RegisterVariable(&r_equalize_entities_by);
4165         Cvar_RegisterVariable(&r_equalize_entities_to);
4166         Cvar_RegisterVariable(&r_depthfirst);
4167         Cvar_RegisterVariable(&r_useinfinitefarclip);
4168         Cvar_RegisterVariable(&r_farclip_base);
4169         Cvar_RegisterVariable(&r_farclip_world);
4170         Cvar_RegisterVariable(&r_nearclip);
4171         Cvar_RegisterVariable(&r_deformvertexes);
4172         Cvar_RegisterVariable(&r_transparent);
4173         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4174         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4175         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4176         Cvar_RegisterVariable(&r_showoverdraw);
4177         Cvar_RegisterVariable(&r_showbboxes);
4178         Cvar_RegisterVariable(&r_showsurfaces);
4179         Cvar_RegisterVariable(&r_showtris);
4180         Cvar_RegisterVariable(&r_shownormals);
4181         Cvar_RegisterVariable(&r_showlighting);
4182         Cvar_RegisterVariable(&r_showshadowvolumes);
4183         Cvar_RegisterVariable(&r_showcollisionbrushes);
4184         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4185         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4186         Cvar_RegisterVariable(&r_showdisabledepthtest);
4187         Cvar_RegisterVariable(&r_drawportals);
4188         Cvar_RegisterVariable(&r_drawentities);
4189         Cvar_RegisterVariable(&r_draw2d);
4190         Cvar_RegisterVariable(&r_drawworld);
4191         Cvar_RegisterVariable(&r_cullentities_trace);
4192         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4193         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4194         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4195         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4196         Cvar_RegisterVariable(&r_sortentities);
4197         Cvar_RegisterVariable(&r_drawviewmodel);
4198         Cvar_RegisterVariable(&r_drawexteriormodel);
4199         Cvar_RegisterVariable(&r_speeds);
4200         Cvar_RegisterVariable(&r_fullbrights);
4201         Cvar_RegisterVariable(&r_wateralpha);
4202         Cvar_RegisterVariable(&r_dynamic);
4203         Cvar_RegisterVariable(&r_fakelight);
4204         Cvar_RegisterVariable(&r_fakelight_intensity);
4205         Cvar_RegisterVariable(&r_fullbright);
4206         Cvar_RegisterVariable(&r_shadows);
4207         Cvar_RegisterVariable(&r_shadows_darken);
4208         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4209         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4210         Cvar_RegisterVariable(&r_shadows_throwdistance);
4211         Cvar_RegisterVariable(&r_shadows_throwdirection);
4212         Cvar_RegisterVariable(&r_shadows_focus);
4213         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4214         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4215         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4216         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4217         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4218         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4219         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4220         Cvar_RegisterVariable(&r_fog_exp2);
4221         Cvar_RegisterVariable(&r_fog_clear);
4222         Cvar_RegisterVariable(&r_drawfog);
4223         Cvar_RegisterVariable(&r_transparentdepthmasking);
4224         Cvar_RegisterVariable(&r_transparent_sortmindist);
4225         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4226         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4227         Cvar_RegisterVariable(&r_texture_dds_load);
4228         Cvar_RegisterVariable(&r_texture_dds_save);
4229         Cvar_RegisterVariable(&r_textureunits);
4230         Cvar_RegisterVariable(&gl_combine);
4231         Cvar_RegisterVariable(&r_usedepthtextures);
4232         Cvar_RegisterVariable(&r_viewfbo);
4233         Cvar_RegisterVariable(&r_viewscale);
4234         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4235         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4236         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4237         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4238         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4239         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4240         Cvar_RegisterVariable(&r_glsl);
4241         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4242         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4243         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4244         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4245         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4246         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4247         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4248         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4249         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4250         Cvar_RegisterVariable(&r_glsl_postprocess);
4251         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4252         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4253         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4254         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4255         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4256         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4257         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4258         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4259         Cvar_RegisterVariable(&r_celshading);
4260         Cvar_RegisterVariable(&r_celoutlines);
4261
4262         Cvar_RegisterVariable(&r_water);
4263         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4264         Cvar_RegisterVariable(&r_water_clippingplanebias);
4265         Cvar_RegisterVariable(&r_water_refractdistort);
4266         Cvar_RegisterVariable(&r_water_reflectdistort);
4267         Cvar_RegisterVariable(&r_water_scissormode);
4268         Cvar_RegisterVariable(&r_water_lowquality);
4269         Cvar_RegisterVariable(&r_water_hideplayer);
4270         Cvar_RegisterVariable(&r_water_fbo);
4271
4272         Cvar_RegisterVariable(&r_lerpsprites);
4273         Cvar_RegisterVariable(&r_lerpmodels);
4274         Cvar_RegisterVariable(&r_lerplightstyles);
4275         Cvar_RegisterVariable(&r_waterscroll);
4276         Cvar_RegisterVariable(&r_bloom);
4277         Cvar_RegisterVariable(&r_bloom_colorscale);
4278         Cvar_RegisterVariable(&r_bloom_brighten);
4279         Cvar_RegisterVariable(&r_bloom_blur);
4280         Cvar_RegisterVariable(&r_bloom_resolution);
4281         Cvar_RegisterVariable(&r_bloom_colorexponent);
4282         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4283         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4284         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4285         Cvar_RegisterVariable(&r_hdr_glowintensity);
4286         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4287         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4288         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4289         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4290         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4291         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4292         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4293         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4294         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4295         Cvar_RegisterVariable(&developer_texturelogging);
4296         Cvar_RegisterVariable(&gl_lightmaps);
4297         Cvar_RegisterVariable(&r_test);
4298         Cvar_RegisterVariable(&r_batch_multidraw);
4299         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4300         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4301         Cvar_RegisterVariable(&r_glsl_skeletal);
4302         Cvar_RegisterVariable(&r_glsl_saturation);
4303         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4304         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4305         Cvar_RegisterVariable(&r_framedatasize);
4306         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4307                 Cvar_SetValue("r_fullbrights", 0);
4308         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4309 }
4310
4311 void Render_Init(void)
4312 {
4313         gl_backend_init();
4314         R_Textures_Init();
4315         GL_Main_Init();
4316         Font_Init();
4317         GL_Draw_Init();
4318         R_Shadow_Init();
4319         R_Sky_Init();
4320         GL_Surf_Init();
4321         Sbar_Init();
4322         R_Particles_Init();
4323         R_Explosion_Init();
4324         R_LightningBeams_Init();
4325         Mod_RenderInit();
4326 }
4327
4328 /*
4329 ===============
4330 GL_Init
4331 ===============
4332 */
4333 #ifndef USE_GLES2
4334 extern char *ENGINE_EXTENSIONS;
4335 void GL_Init (void)
4336 {
4337         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4338         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4339         gl_version = (const char *)qglGetString(GL_VERSION);
4340         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4341
4342         if (!gl_extensions)
4343                 gl_extensions = "";
4344         if (!gl_platformextensions)
4345                 gl_platformextensions = "";
4346
4347         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4348         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4349         Con_Printf("GL_VERSION: %s\n", gl_version);
4350         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4351         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4352
4353         VID_CheckExtensions();
4354
4355         // LordHavoc: report supported extensions
4356         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4357
4358         // clear to black (loading plaque will be seen over this)
4359         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4360 }
4361 #endif
4362
4363 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4364 {
4365         int i;
4366         mplane_t *p;
4367         if (r_trippy.integer)
4368                 return false;
4369         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4370         {
4371                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4372                 if (i == 4)
4373                         continue;
4374                 p = r_refdef.view.frustum + i;
4375                 switch(p->signbits)
4376                 {
4377                 default:
4378                 case 0:
4379                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4380                                 return true;
4381                         break;
4382                 case 1:
4383                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4384                                 return true;
4385                         break;
4386                 case 2:
4387                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4388                                 return true;
4389                         break;
4390                 case 3:
4391                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4392                                 return true;
4393                         break;
4394                 case 4:
4395                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4396                                 return true;
4397                         break;
4398                 case 5:
4399                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4400                                 return true;
4401                         break;
4402                 case 6:
4403                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4404                                 return true;
4405                         break;
4406                 case 7:
4407                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4408                                 return true;
4409                         break;
4410                 }
4411         }
4412         return false;
4413 }
4414
4415 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4416 {
4417         int i;
4418         const mplane_t *p;
4419         if (r_trippy.integer)
4420                 return false;
4421         for (i = 0;i < numplanes;i++)
4422         {
4423                 p = planes + i;
4424                 switch(p->signbits)
4425                 {
4426                 default:
4427                 case 0:
4428                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4429                                 return true;
4430                         break;
4431                 case 1:
4432                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4433                                 return true;
4434                         break;
4435                 case 2:
4436                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4437                                 return true;
4438                         break;
4439                 case 3:
4440                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 4:
4444                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 case 5:
4448                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 case 6:
4452                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 case 7:
4456                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 }
4460         }
4461         return false;
4462 }
4463
4464 //==================================================================================
4465
4466 // LordHavoc: this stores temporary data used within the same frame
4467
4468 typedef struct r_framedata_mem_s
4469 {
4470         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4471         size_t size; // how much usable space
4472         size_t current; // how much space in use
4473         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4474         size_t wantedsize; // how much space was allocated
4475         unsigned char *data; // start of real data (16byte aligned)
4476 }
4477 r_framedata_mem_t;
4478
4479 static r_framedata_mem_t *r_framedata_mem;
4480
4481 void R_FrameData_Reset(void)
4482 {
4483         while (r_framedata_mem)
4484         {
4485                 r_framedata_mem_t *next = r_framedata_mem->purge;
4486                 Mem_Free(r_framedata_mem);
4487                 r_framedata_mem = next;
4488         }
4489 }
4490
4491 static void R_FrameData_Resize(void)
4492 {
4493         size_t wantedsize;
4494         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4495         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4496         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4497         {
4498                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4499                 newmem->wantedsize = wantedsize;
4500                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4501                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4502                 newmem->current = 0;
4503                 newmem->mark = 0;
4504                 newmem->purge = r_framedata_mem;
4505                 r_framedata_mem = newmem;
4506         }
4507 }
4508
4509 void R_FrameData_NewFrame(void)
4510 {
4511         R_FrameData_Resize();
4512         if (!r_framedata_mem)
4513                 return;
4514         // if we ran out of space on the last frame, free the old memory now
4515         while (r_framedata_mem->purge)
4516         {
4517                 // repeatedly remove the second item in the list, leaving only head
4518                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4519                 Mem_Free(r_framedata_mem->purge);
4520                 r_framedata_mem->purge = next;
4521         }
4522         // reset the current mem pointer
4523         r_framedata_mem->current = 0;
4524         r_framedata_mem->mark = 0;
4525 }
4526
4527 void *R_FrameData_Alloc(size_t size)
4528 {
4529         void *data;
4530
4531         // align to 16 byte boundary - the data pointer is already aligned, so we
4532         // only need to ensure the size of every allocation is also aligned
4533         size = (size + 15) & ~15;
4534
4535         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4536         {
4537                 // emergency - we ran out of space, allocate more memory
4538                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4539                 R_FrameData_Resize();
4540         }
4541
4542         data = r_framedata_mem->data + r_framedata_mem->current;
4543         r_framedata_mem->current += size;
4544
4545         // count the usage for stats
4546         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4547         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4548
4549         return (void *)data;
4550 }
4551
4552 void *R_FrameData_Store(size_t size, void *data)
4553 {
4554         void *d = R_FrameData_Alloc(size);
4555         if (d && data)
4556                 memcpy(d, data, size);
4557         return d;
4558 }
4559
4560 void R_FrameData_SetMark(void)
4561 {
4562         if (!r_framedata_mem)
4563                 return;
4564         r_framedata_mem->mark = r_framedata_mem->current;
4565 }
4566
4567 void R_FrameData_ReturnToMark(void)
4568 {
4569         if (!r_framedata_mem)
4570                 return;
4571         r_framedata_mem->current = r_framedata_mem->mark;
4572 }
4573
4574 //==================================================================================
4575
4576 // LordHavoc: animcache originally written by Echon, rewritten since then
4577
4578 /**
4579  * Animation cache prevents re-generating mesh data for an animated model
4580  * multiple times in one frame for lighting, shadowing, reflections, etc.
4581  */
4582
4583 void R_AnimCache_Free(void)
4584 {
4585 }
4586
4587 void R_AnimCache_ClearCache(void)
4588 {
4589         int i;
4590         entity_render_t *ent;
4591
4592         for (i = 0;i < r_refdef.scene.numentities;i++)
4593         {
4594                 ent = r_refdef.scene.entities[i];
4595                 ent->animcache_vertex3f = NULL;
4596                 ent->animcache_normal3f = NULL;
4597                 ent->animcache_svector3f = NULL;
4598                 ent->animcache_tvector3f = NULL;
4599                 ent->animcache_vertexmesh = NULL;
4600                 ent->animcache_vertex3fbuffer = NULL;
4601                 ent->animcache_vertexmeshbuffer = NULL;
4602                 ent->animcache_skeletaltransform3x4 = NULL;
4603         }
4604 }
4605
4606 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4607 {
4608         int i;
4609
4610         // check if we need the meshbuffers
4611         if (!vid.useinterleavedarrays)
4612                 return;
4613
4614         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4615                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4616         // TODO: upload vertex3f buffer?
4617         if (ent->animcache_vertexmesh)
4618         {
4619                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4620                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4621                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4622                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4623                 for (i = 0;i < numvertices;i++)
4624                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4625                 if (ent->animcache_svector3f)
4626                         for (i = 0;i < numvertices;i++)
4627                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4628                 if (ent->animcache_tvector3f)
4629                         for (i = 0;i < numvertices;i++)
4630                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4631                 if (ent->animcache_normal3f)
4632                         for (i = 0;i < numvertices;i++)
4633                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4634                 // TODO: upload vertexmeshbuffer?
4635         }
4636 }
4637
4638 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4639 {
4640         dp_model_t *model = ent->model;
4641         int numvertices;
4642
4643         // cache skeletal animation data first (primarily for gpu-skinning)
4644         if (!ent->animcache_skeletaltransform3x4 && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4645         {
4646                 int i;
4647                 int blends;
4648                 const skeleton_t *skeleton = ent->skeleton;
4649                 const frameblend_t *frameblend = ent->frameblend;
4650                 float *boneposerelative;
4651                 float m[12];
4652                 static float bonepose[256][12];
4653                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4654                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4655                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4656                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4657                 boneposerelative = ent->animcache_skeletaltransform3x4;
4658                 if (skeleton && !skeleton->relativetransforms)
4659                         skeleton = NULL;
4660                 // resolve hierarchy and make relative transforms (deforms) which the shader wants
4661                 if (skeleton)
4662                 {
4663                         for (i = 0;i < model->num_bones;i++)
4664                         {
4665                                 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
4666                                 if (model->data_bones[i].parent >= 0)
4667                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4668                                 else
4669                                         memcpy(bonepose[i], m, sizeof(m));
4670
4671                                 // create a relative deformation matrix to describe displacement
4672                                 // from the base mesh, which is used by the actual weighting
4673                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4674                         }
4675                 }
4676                 else
4677                 {
4678                         for (i = 0;i < model->num_bones;i++)
4679                         {
4680                                 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
4681                                 float lerp = frameblend[0].lerp,
4682                                         tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4683                                         rx = pose7s[3] * lerp,
4684                                         ry = pose7s[4] * lerp,
4685                                         rz = pose7s[5] * lerp,
4686                                         rw = pose7s[6] * lerp,
4687                                         dx = tx*rw + ty*rz - tz*ry,
4688                                         dy = -tx*rz + ty*rw + tz*rx,
4689                                         dz = tx*ry - ty*rx + tz*rw,
4690                                         dw = -tx*rx - ty*ry - tz*rz,
4691                                         scale, sx, sy, sz, sw;
4692                                 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
4693                                 {
4694                                         const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
4695                                         float lerp = frameblend[blends].lerp,
4696                                                 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4697                                                 qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
4698                                         if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
4699                                         qx *= lerp;
4700                                         qy *= lerp;
4701                                         qz *= lerp;
4702                                         qw *= lerp;
4703                                         rx += qx;
4704                                         ry += qy;
4705                                         rz += qz;
4706                                         rw += qw;
4707                                         dx += tx*qw + ty*qz - tz*qy;
4708                                         dy += -tx*qz + ty*qw + tz*qx;
4709                                         dz += tx*qy - ty*qx + tz*qw;
4710                                         dw += -tx*qx - ty*qy - tz*qz;
4711                                 }
4712                                 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
4713                                 sx = rx * scale;
4714                                 sy = ry * scale;
4715                                 sz = rz * scale;
4716                                 sw = rw * scale;
4717                                 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
4718                                 m[1] = 2*(sx*ry - sw*rz);
4719                                 m[2] = 2*(sx*rz + sw*ry);
4720                                 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
4721                                 m[4] = 2*(sx*ry + sw*rz);
4722                                 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
4723                                 m[6] = 2*(sy*rz - sw*rx);
4724                                 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
4725                                 m[8] = 2*(sx*rz - sw*ry);
4726                                 m[9] = 2*(sy*rz + sw*rx);
4727                                 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
4728                                 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
4729                                 if (i == r_skeletal_debugbone.integer)
4730                                         m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
4731                                 m[3] *= r_skeletal_debugtranslatex.value;
4732                                 m[7] *= r_skeletal_debugtranslatey.value;
4733                                 m[11] *= r_skeletal_debugtranslatez.value;
4734                                 if (model->data_bones[i].parent >= 0)
4735                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4736                                 else
4737                                         memcpy(bonepose[i], m, sizeof(m));
4738                                 // create a relative deformation matrix to describe displacement
4739                                 // from the base mesh, which is used by the actual weighting
4740                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4741                         }
4742                 }
4743         }
4744
4745         // see if it's already cached this frame
4746         if (ent->animcache_vertex3f)
4747         {
4748                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4749                 if (wantnormals || wanttangents)
4750                 {
4751                         if (ent->animcache_normal3f)
4752                                 wantnormals = false;
4753                         if (ent->animcache_svector3f)
4754                                 wanttangents = false;
4755                         if (wantnormals || wanttangents)
4756                         {
4757                                 numvertices = model->surfmesh.num_vertices;
4758                                 if (wantnormals)
4759                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4760                                 if (wanttangents)
4761                                 {
4762                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4763                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4764                                 }
4765                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4766                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4767                                 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4768                                 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4769                                 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4770                         }
4771                 }
4772         }
4773         else
4774         {
4775                 // see if this ent is worth caching
4776                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4777                         return false;
4778                 // skip entity if the shader backend has a cheaper way
4779                 if (model->surfmesh.data_skeletalindex4ub && r_glsl_skeletal.integer && !r_showsurfaces.integer) // FIXME add r_showsurfaces support to GLSL skeletal!
4780                 {
4781                         switch (vid.renderpath)
4782                         {
4783                         case RENDERPATH_GL20:
4784                                 return false;
4785                         case RENDERPATH_GL11:
4786                         case RENDERPATH_GL13:
4787                         case RENDERPATH_GLES1:
4788                         case RENDERPATH_GLES2:
4789                         case RENDERPATH_D3D9:
4790                         case RENDERPATH_D3D10:
4791                         case RENDERPATH_D3D11:
4792                         case RENDERPATH_SOFT:
4793                                 break;
4794                         }
4795                 }
4796                 // get some memory for this entity and generate mesh data
4797                 numvertices = model->surfmesh.num_vertices;
4798                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4799                 if (wantnormals)
4800                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4801                 if (wanttangents)
4802                 {
4803                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4804                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4805                 }
4806                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4807                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4808                 if (wantnormals || wanttangents)
4809                 {
4810                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4811                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4812                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4813                 }
4814                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4815                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4816                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4817         }
4818         return true;
4819 }
4820
4821 void R_AnimCache_CacheVisibleEntities(void)
4822 {
4823         int i;
4824         qboolean wantnormals = true;
4825         qboolean wanttangents = !r_showsurfaces.integer;
4826
4827         switch(vid.renderpath)
4828         {
4829         case RENDERPATH_GL20:
4830         case RENDERPATH_D3D9:
4831         case RENDERPATH_D3D10:
4832         case RENDERPATH_D3D11:
4833         case RENDERPATH_GLES2:
4834                 break;
4835         case RENDERPATH_GL11:
4836         case RENDERPATH_GL13:
4837         case RENDERPATH_GLES1:
4838                 wanttangents = false;
4839                 break;
4840         case RENDERPATH_SOFT:
4841                 break;
4842         }
4843
4844         if (r_shownormals.integer)
4845                 wanttangents = wantnormals = true;
4846
4847         // TODO: thread this
4848         // NOTE: R_PrepareRTLights() also caches entities
4849
4850         for (i = 0;i < r_refdef.scene.numentities;i++)
4851                 if (r_refdef.viewcache.entityvisible[i])
4852                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4853 }
4854
4855 //==================================================================================
4856
4857 extern cvar_t r_overheadsprites_pushback;
4858
4859 static void R_View_UpdateEntityLighting (void)
4860 {
4861         int i;
4862         entity_render_t *ent;
4863         vec3_t tempdiffusenormal, avg;
4864         vec_t f, fa, fd, fdd;
4865         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4866
4867         for (i = 0;i < r_refdef.scene.numentities;i++)
4868         {
4869                 ent = r_refdef.scene.entities[i];
4870
4871                 // skip unseen models
4872                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4873                         continue;
4874
4875                 // skip bsp models
4876                 if (ent->model && ent->model == cl.worldmodel)
4877                 {
4878                         // TODO: use modellight for r_ambient settings on world?
4879                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4880                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4881                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4882                         continue;
4883                 }
4884                 
4885                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4886                 {
4887                         // aleady updated by CSQC
4888                         // TODO: force modellight on BSP models in this case?
4889                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4890                 }
4891                 else
4892                 {
4893                         // fetch the lighting from the worldmodel data
4894                         VectorClear(ent->modellight_ambient);
4895                         VectorClear(ent->modellight_diffuse);
4896                         VectorClear(tempdiffusenormal);
4897                         if (ent->flags & RENDER_LIGHT)
4898                         {
4899                                 vec3_t org;
4900                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4901
4902                                 // complete lightning for lit sprites
4903                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4904                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4905                                 {
4906                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4907                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4908                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4909                                 }
4910                                 else
4911                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4912
4913                                 if(ent->flags & RENDER_EQUALIZE)
4914                                 {
4915                                         // first fix up ambient lighting...
4916                                         if(r_equalize_entities_minambient.value > 0)
4917                                         {
4918                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4919                                                 if(fd > 0)
4920                                                 {
4921                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4922                                                         if(fa < r_equalize_entities_minambient.value * fd)
4923                                                         {
4924                                                                 // solve:
4925                                                                 //   fa'/fd' = minambient
4926                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4927                                                                 //   ...
4928                                                                 //   fa' = fd' * minambient
4929                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4930                                                                 //   ...
4931                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4932                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4933                                                                 //   ...
4934                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4935                                                                 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
4936                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4937                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4938                                                         }
4939                                                 }
4940                                         }
4941
4942                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4943                                         {
4944                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4945                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4946                                                 f = fa + 0.25 * fd;
4947                                                 if(f > 0)
4948                                                 {
4949                                                         // adjust brightness and saturation to target
4950                                                         avg[0] = avg[1] = avg[2] = fa / f;
4951                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4952                                                         avg[0] = avg[1] = avg[2] = fd / f;
4953                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4954                                                 }
4955                                         }
4956                                 }
4957                         }
4958                         else // highly rare
4959                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4960                 }
4961
4962                 // move the light direction into modelspace coordinates for lighting code
4963                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4964                 if(VectorLength2(ent->modellight_lightdir) == 0)
4965                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4966                 VectorNormalize(ent->modellight_lightdir);
4967         }
4968 }
4969
4970 #define MAX_LINEOFSIGHTTRACES 64
4971
4972 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4973 {
4974         int i;
4975         vec3_t boxmins, boxmaxs;
4976         vec3_t start;
4977         vec3_t end;
4978         dp_model_t *model = r_refdef.scene.worldmodel;
4979
4980         if (!model || !model->brush.TraceLineOfSight)
4981                 return true;
4982
4983         // expand the box a little
4984         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4985         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4986         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4987         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4988         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4989         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4990
4991         // return true if eye is inside enlarged box
4992         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4993                 return true;
4994
4995         // try center
4996         VectorCopy(eye, start);
4997         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4998         if (model->brush.TraceLineOfSight(model, start, end))
4999                 return true;
5000
5001         // try various random positions
5002         for (i = 0;i < numsamples;i++)
5003         {
5004                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5005                 if (model->brush.TraceLineOfSight(model, start, end))
5006                         return true;
5007         }
5008
5009         return false;
5010 }
5011
5012
5013 static void R_View_UpdateEntityVisible (void)
5014 {
5015         int i;
5016         int renderimask;
5017         int samples;
5018         entity_render_t *ent;
5019
5020         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5021                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5022                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5023                 :                                                          RENDER_EXTERIORMODEL;
5024         if (!r_drawviewmodel.integer)
5025                 renderimask |= RENDER_VIEWMODEL;
5026         if (!r_drawexteriormodel.integer)
5027                 renderimask |= RENDER_EXTERIORMODEL;
5028         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5029         {
5030                 // worldmodel can check visibility
5031                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5032                 for (i = 0;i < r_refdef.scene.numentities;i++)
5033                 {
5034                         ent = r_refdef.scene.entities[i];
5035                         if (!(ent->flags & renderimask))
5036                         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)))
5037                         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))
5038                                 r_refdef.viewcache.entityvisible[i] = true;
5039                 }
5040         }
5041         else
5042         {
5043                 // no worldmodel or it can't check visibility
5044                 for (i = 0;i < r_refdef.scene.numentities;i++)
5045                 {
5046                         ent = r_refdef.scene.entities[i];
5047                         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));
5048                 }
5049         }
5050         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5051                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5052         {
5053                 for (i = 0;i < r_refdef.scene.numentities;i++)
5054                 {
5055                         if (!r_refdef.viewcache.entityvisible[i])
5056                                 continue;
5057                         ent = r_refdef.scene.entities[i];
5058                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5059                         {
5060                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5061                                 if (samples < 0)
5062                                         continue; // temp entities do pvs only
5063                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5064                                         ent->last_trace_visibility = realtime;
5065                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5066                                         r_refdef.viewcache.entityvisible[i] = 0;
5067                         }
5068                 }
5069         }
5070 }
5071
5072 /// only used if skyrendermasked, and normally returns false
5073 static int R_DrawBrushModelsSky (void)
5074 {
5075         int i, sky;
5076         entity_render_t *ent;
5077
5078         sky = false;
5079         for (i = 0;i < r_refdef.scene.numentities;i++)
5080         {
5081                 if (!r_refdef.viewcache.entityvisible[i])
5082                         continue;
5083                 ent = r_refdef.scene.entities[i];
5084                 if (!ent->model || !ent->model->DrawSky)
5085                         continue;
5086                 ent->model->DrawSky(ent);
5087                 sky = true;
5088         }
5089         return sky;
5090 }
5091
5092 static void R_DrawNoModel(entity_render_t *ent);
5093 static void R_DrawModels(void)
5094 {
5095         int i;
5096         entity_render_t *ent;
5097
5098         for (i = 0;i < r_refdef.scene.numentities;i++)
5099         {
5100                 if (!r_refdef.viewcache.entityvisible[i])
5101                         continue;
5102                 ent = r_refdef.scene.entities[i];
5103                 r_refdef.stats[r_stat_entities]++;
5104                 /*
5105                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5106                 {
5107                         vec3_t f, l, u, o;
5108                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5109                         Con_Printf("R_DrawModels\n");
5110                         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]);
5111                         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);
5112                         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);
5113                 }
5114                 */
5115                 if (ent->model && ent->model->Draw != NULL)
5116                         ent->model->Draw(ent);
5117                 else
5118                         R_DrawNoModel(ent);
5119         }
5120 }
5121
5122 static void R_DrawModelsDepth(void)
5123 {
5124         int i;
5125         entity_render_t *ent;
5126
5127         for (i = 0;i < r_refdef.scene.numentities;i++)
5128         {
5129                 if (!r_refdef.viewcache.entityvisible[i])
5130                         continue;
5131                 ent = r_refdef.scene.entities[i];
5132                 if (ent->model && ent->model->DrawDepth != NULL)
5133                         ent->model->DrawDepth(ent);
5134         }
5135 }
5136
5137 static void R_DrawModelsDebug(void)
5138 {
5139         int i;
5140         entity_render_t *ent;
5141
5142         for (i = 0;i < r_refdef.scene.numentities;i++)
5143         {
5144                 if (!r_refdef.viewcache.entityvisible[i])
5145                         continue;
5146                 ent = r_refdef.scene.entities[i];
5147                 if (ent->model && ent->model->DrawDebug != NULL)
5148                         ent->model->DrawDebug(ent);
5149         }
5150 }
5151
5152 static void R_DrawModelsAddWaterPlanes(void)
5153 {
5154         int i;
5155         entity_render_t *ent;
5156
5157         for (i = 0;i < r_refdef.scene.numentities;i++)
5158         {
5159                 if (!r_refdef.viewcache.entityvisible[i])
5160                         continue;
5161                 ent = r_refdef.scene.entities[i];
5162                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5163                         ent->model->DrawAddWaterPlanes(ent);
5164         }
5165 }
5166
5167 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}};
5168
5169 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5170 {
5171         if (r_hdr_irisadaptation.integer)
5172         {
5173                 vec3_t p;
5174                 vec3_t ambient;
5175                 vec3_t diffuse;
5176                 vec3_t diffusenormal;
5177                 vec3_t forward;
5178                 vec_t brightness = 0.0f;
5179                 vec_t goal;
5180                 vec_t current;
5181                 vec_t d;
5182                 int c;
5183                 VectorCopy(r_refdef.view.forward, forward);
5184                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5185                 {
5186                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5187                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5188                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5189                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5190                         d = DotProduct(forward, diffusenormal);
5191                         brightness += VectorLength(ambient);
5192                         if (d > 0)
5193                                 brightness += d * VectorLength(diffuse);
5194                 }
5195                 brightness *= 1.0f / c;
5196                 brightness += 0.00001f; // make sure it's never zero
5197                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5198                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5199                 current = r_hdr_irisadaptation_value.value;
5200                 if (current < goal)
5201                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5202                 else if (current > goal)
5203                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5204                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5205                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5206         }
5207         else if (r_hdr_irisadaptation_value.value != 1.0f)
5208                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5209 }
5210
5211 static void R_View_SetFrustum(const int *scissor)
5212 {
5213         int i;
5214         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5215         vec3_t forward, left, up, origin, v;
5216
5217         if(scissor)
5218         {
5219                 // flipped x coordinates (because x points left here)
5220                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5221                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5222
5223                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5224                 switch(vid.renderpath)
5225                 {
5226                         case RENDERPATH_D3D9:
5227                         case RENDERPATH_D3D10:
5228                         case RENDERPATH_D3D11:
5229                                 // non-flipped y coordinates
5230                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5231                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5232                                 break;
5233                         case RENDERPATH_SOFT:
5234                         case RENDERPATH_GL11:
5235                         case RENDERPATH_GL13:
5236                         case RENDERPATH_GL20:
5237                         case RENDERPATH_GLES1:
5238                         case RENDERPATH_GLES2:
5239                                 // non-flipped y coordinates
5240                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5241                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5242                                 break;
5243                 }
5244         }
5245
5246         // we can't trust r_refdef.view.forward and friends in reflected scenes
5247         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5248
5249 #if 0
5250         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5251         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5252         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5253         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5254         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5255         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5256         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5257         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5258         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5259         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5260         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5261         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5262 #endif
5263
5264 #if 0
5265         zNear = r_refdef.nearclip;
5266         nudge = 1.0 - 1.0 / (1<<23);
5267         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5268         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5269         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5270         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5271         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5272         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5273         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5274         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5275 #endif
5276
5277
5278
5279 #if 0
5280         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5281         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5282         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5283         r_refdef.view.frustum[0].dist = m[15] - m[12];
5284
5285         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5286         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5287         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5288         r_refdef.view.frustum[1].dist = m[15] + m[12];
5289
5290         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5291         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5292         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5293         r_refdef.view.frustum[2].dist = m[15] - m[13];
5294
5295         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5296         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5297         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5298         r_refdef.view.frustum[3].dist = m[15] + m[13];
5299
5300         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5301         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5302         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5303         r_refdef.view.frustum[4].dist = m[15] - m[14];
5304
5305         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5306         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5307         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5308         r_refdef.view.frustum[5].dist = m[15] + m[14];
5309 #endif
5310
5311         if (r_refdef.view.useperspective)
5312         {
5313                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5314                 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]);
5315                 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]);
5316                 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]);
5317                 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]);
5318
5319                 // then the normals from the corners relative to origin
5320                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5321                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5322                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5323                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5324
5325                 // in a NORMAL view, forward cross left == up
5326                 // in a REFLECTED view, forward cross left == down
5327                 // so our cross products above need to be adjusted for a left handed coordinate system
5328                 CrossProduct(forward, left, v);
5329                 if(DotProduct(v, up) < 0)
5330                 {
5331                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5332                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5333                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5334                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5335                 }
5336
5337                 // Leaving those out was a mistake, those were in the old code, and they
5338                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5339                 // I couldn't reproduce it after adding those normalizations. --blub
5340                 VectorNormalize(r_refdef.view.frustum[0].normal);
5341                 VectorNormalize(r_refdef.view.frustum[1].normal);
5342                 VectorNormalize(r_refdef.view.frustum[2].normal);
5343                 VectorNormalize(r_refdef.view.frustum[3].normal);
5344
5345                 // make the corners absolute
5346                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5347                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5348                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5349                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5350
5351                 // one more normal
5352                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5353
5354                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5355                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5356                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5357                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5358                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5359         }
5360         else
5361         {
5362                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5363                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5364                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5365                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5366                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5367                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5368                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5369                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5370                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5371                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5372         }
5373         r_refdef.view.numfrustumplanes = 5;
5374
5375         if (r_refdef.view.useclipplane)
5376         {
5377                 r_refdef.view.numfrustumplanes = 6;
5378                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5379         }
5380
5381         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5382                 PlaneClassify(r_refdef.view.frustum + i);
5383
5384         // LordHavoc: note to all quake engine coders, Quake had a special case
5385         // for 90 degrees which assumed a square view (wrong), so I removed it,
5386         // Quake2 has it disabled as well.
5387
5388         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5389         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5390         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5391         //PlaneClassify(&frustum[0]);
5392
5393         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5394         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5395         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5396         //PlaneClassify(&frustum[1]);
5397
5398         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5399         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5400         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5401         //PlaneClassify(&frustum[2]);
5402
5403         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5404         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5405         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5406         //PlaneClassify(&frustum[3]);
5407
5408         // nearclip plane
5409         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5410         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5411         //PlaneClassify(&frustum[4]);
5412 }
5413
5414 static void R_View_UpdateWithScissor(const int *myscissor)
5415 {
5416         R_Main_ResizeViewCache();
5417         R_View_SetFrustum(myscissor);
5418         R_View_WorldVisibility(r_refdef.view.useclipplane);
5419         R_View_UpdateEntityVisible();
5420         R_View_UpdateEntityLighting();
5421 }
5422
5423 static void R_View_Update(void)
5424 {
5425         R_Main_ResizeViewCache();
5426         R_View_SetFrustum(NULL);
5427         R_View_WorldVisibility(r_refdef.view.useclipplane);
5428         R_View_UpdateEntityVisible();
5429         R_View_UpdateEntityLighting();
5430 }
5431
5432 float viewscalefpsadjusted = 1.0f;
5433
5434 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5435 {
5436         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5437         scale = bound(0.03125f, scale, 1.0f);
5438         *outwidth = (int)ceil(width * scale);
5439         *outheight = (int)ceil(height * scale);
5440 }
5441
5442 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5443 {
5444         const float *customclipplane = NULL;
5445         float plane[4];
5446         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5447         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5448         {
5449                 // LordHavoc: couldn't figure out how to make this approach the
5450                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5451                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5452                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5453                         dist = r_refdef.view.clipplane.dist;
5454                 plane[0] = r_refdef.view.clipplane.normal[0];
5455                 plane[1] = r_refdef.view.clipplane.normal[1];
5456                 plane[2] = r_refdef.view.clipplane.normal[2];
5457                 plane[3] = -dist;
5458                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5459         }
5460
5461         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5462         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5463
5464         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5465         if (!r_refdef.view.useperspective)
5466                 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);
5467         else if (vid.stencil && r_useinfinitefarclip.integer)
5468                 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);
5469         else
5470                 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);
5471         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5472         R_SetViewport(&r_refdef.view.viewport);
5473         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5474         {
5475                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5476                 float screenplane[4];
5477                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5478                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5479                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5480                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5481                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5482         }
5483 }
5484
5485 void R_EntityMatrix(const matrix4x4_t *matrix)
5486 {
5487         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5488         {
5489                 gl_modelmatrixchanged = false;
5490                 gl_modelmatrix = *matrix;
5491                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5492                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5493                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5494                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5495                 CHECKGLERROR
5496                 switch(vid.renderpath)
5497                 {
5498                 case RENDERPATH_D3D9:
5499 #ifdef SUPPORTD3D
5500                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5501                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5502 #endif
5503                         break;
5504                 case RENDERPATH_D3D10:
5505                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5506                         break;
5507                 case RENDERPATH_D3D11:
5508                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5509                         break;
5510                 case RENDERPATH_GL11:
5511                 case RENDERPATH_GL13:
5512                 case RENDERPATH_GLES1:
5513                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5514                         break;
5515                 case RENDERPATH_SOFT:
5516                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5517                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5518                         break;
5519                 case RENDERPATH_GL20:
5520                 case RENDERPATH_GLES2:
5521                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5522                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5523                         break;
5524                 }
5525         }
5526 }
5527
5528 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5529 {
5530         r_viewport_t viewport;
5531
5532         CHECKGLERROR
5533
5534         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5535         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);
5536         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5537         R_SetViewport(&viewport);
5538         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5539         GL_Color(1, 1, 1, 1);
5540         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5541         GL_BlendFunc(GL_ONE, GL_ZERO);
5542         GL_ScissorTest(false);
5543         GL_DepthMask(false);
5544         GL_DepthRange(0, 1);
5545         GL_DepthTest(false);
5546         GL_DepthFunc(GL_LEQUAL);
5547         R_EntityMatrix(&identitymatrix);
5548         R_Mesh_ResetTextureState();
5549         GL_PolygonOffset(0, 0);
5550         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5551         switch(vid.renderpath)
5552         {
5553         case RENDERPATH_GL11:
5554         case RENDERPATH_GL13:
5555         case RENDERPATH_GL20:
5556         case RENDERPATH_GLES1:
5557         case RENDERPATH_GLES2:
5558                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5559                 break;
5560         case RENDERPATH_D3D9:
5561         case RENDERPATH_D3D10:
5562         case RENDERPATH_D3D11:
5563         case RENDERPATH_SOFT:
5564                 break;
5565         }
5566         GL_CullFace(GL_NONE);
5567
5568         CHECKGLERROR
5569 }
5570
5571 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5572 {
5573         DrawQ_Finish();
5574
5575         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5576 }
5577
5578 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5579 {
5580         DrawQ_Finish();
5581
5582         R_SetupView(true, fbo, depthtexture, colortexture);
5583         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5584         GL_Color(1, 1, 1, 1);
5585         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5586         GL_BlendFunc(GL_ONE, GL_ZERO);
5587         GL_ScissorTest(true);
5588         GL_DepthMask(true);
5589         GL_DepthRange(0, 1);
5590         GL_DepthTest(true);
5591         GL_DepthFunc(GL_LEQUAL);
5592         R_EntityMatrix(&identitymatrix);
5593         R_Mesh_ResetTextureState();
5594         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5595         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5596         switch(vid.renderpath)
5597         {
5598         case RENDERPATH_GL11:
5599         case RENDERPATH_GL13:
5600         case RENDERPATH_GL20:
5601         case RENDERPATH_GLES1:
5602         case RENDERPATH_GLES2:
5603                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5604                 break;
5605         case RENDERPATH_D3D9:
5606         case RENDERPATH_D3D10:
5607         case RENDERPATH_D3D11:
5608         case RENDERPATH_SOFT:
5609                 break;
5610         }
5611         GL_CullFace(r_refdef.view.cullface_back);
5612 }
5613
5614 /*
5615 ================
5616 R_RenderView_UpdateViewVectors
5617 ================
5618 */
5619 void R_RenderView_UpdateViewVectors(void)
5620 {
5621         // break apart the view matrix into vectors for various purposes
5622         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5623         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5624         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5625         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5626         // make an inverted copy of the view matrix for tracking sprites
5627         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5628 }
5629
5630 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5631 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5632
5633 static void R_Water_StartFrame(void)
5634 {
5635         int i;
5636         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5637         r_waterstate_waterplane_t *p;
5638         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;
5639
5640         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5641                 return;
5642
5643         switch(vid.renderpath)
5644         {
5645         case RENDERPATH_GL20:
5646         case RENDERPATH_D3D9:
5647         case RENDERPATH_D3D10:
5648         case RENDERPATH_D3D11:
5649         case RENDERPATH_SOFT:
5650         case RENDERPATH_GLES2:
5651                 break;
5652         case RENDERPATH_GL11:
5653         case RENDERPATH_GL13:
5654         case RENDERPATH_GLES1:
5655                 return;
5656         }
5657
5658         // set waterwidth and waterheight to the water resolution that will be
5659         // used (often less than the screen resolution for faster rendering)
5660         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5661
5662         // calculate desired texture sizes
5663         // can't use water if the card does not support the texture size
5664         if (!r_water.integer || r_showsurfaces.integer)
5665                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5666         else if (vid.support.arb_texture_non_power_of_two)
5667         {
5668                 texturewidth = waterwidth;
5669                 textureheight = waterheight;
5670                 camerawidth = waterwidth;
5671                 cameraheight = waterheight;
5672         }
5673         else
5674         {
5675                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5676                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5677                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5678                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5679         }
5680
5681         // allocate textures as needed
5682         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))
5683         {
5684                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5685                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5686                 {
5687                         if (p->texture_refraction)
5688                                 R_FreeTexture(p->texture_refraction);
5689                         p->texture_refraction = NULL;
5690                         if (p->fbo_refraction)
5691                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5692                         p->fbo_refraction = 0;
5693                         if (p->texture_reflection)
5694                                 R_FreeTexture(p->texture_reflection);
5695                         p->texture_reflection = NULL;
5696                         if (p->fbo_reflection)
5697                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5698                         p->fbo_reflection = 0;
5699                         if (p->texture_camera)
5700                                 R_FreeTexture(p->texture_camera);
5701                         p->texture_camera = NULL;
5702                         if (p->fbo_camera)
5703                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5704                         p->fbo_camera = 0;
5705                 }
5706                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5707                 r_fb.water.texturewidth = texturewidth;
5708                 r_fb.water.textureheight = textureheight;
5709                 r_fb.water.camerawidth = camerawidth;
5710                 r_fb.water.cameraheight = cameraheight;
5711         }
5712
5713         if (r_fb.water.texturewidth)
5714         {
5715                 int scaledwidth, scaledheight;
5716
5717                 r_fb.water.enabled = true;
5718
5719                 // water resolution is usually reduced
5720                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5721                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5722                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5723
5724                 // set up variables that will be used in shader setup
5725                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5726                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5727                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5728                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5729         }
5730
5731         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5732         r_fb.water.numwaterplanes = 0;
5733 }
5734
5735 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5736 {
5737         int planeindex, bestplaneindex, vertexindex;
5738         vec3_t mins, maxs, normal, center, v, n;
5739         vec_t planescore, bestplanescore;
5740         mplane_t plane;
5741         r_waterstate_waterplane_t *p;
5742         texture_t *t = R_GetCurrentTexture(surface->texture);
5743
5744         rsurface.texture = t;
5745         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5746         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5747         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5748                 return;
5749         // average the vertex normals, find the surface bounds (after deformvertexes)
5750         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5751         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5752         VectorCopy(n, normal);
5753         VectorCopy(v, mins);
5754         VectorCopy(v, maxs);
5755         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5756         {
5757                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5758                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5759                 VectorAdd(normal, n, normal);
5760                 mins[0] = min(mins[0], v[0]);
5761                 mins[1] = min(mins[1], v[1]);
5762                 mins[2] = min(mins[2], v[2]);
5763                 maxs[0] = max(maxs[0], v[0]);
5764                 maxs[1] = max(maxs[1], v[1]);
5765                 maxs[2] = max(maxs[2], v[2]);
5766         }
5767         VectorNormalize(normal);
5768         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5769
5770         VectorCopy(normal, plane.normal);
5771         VectorNormalize(plane.normal);
5772         plane.dist = DotProduct(center, plane.normal);
5773         PlaneClassify(&plane);
5774         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5775         {
5776                 // skip backfaces (except if nocullface is set)
5777 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5778 //                      return;
5779                 VectorNegate(plane.normal, plane.normal);
5780                 plane.dist *= -1;
5781                 PlaneClassify(&plane);
5782         }
5783
5784
5785         // find a matching plane if there is one
5786         bestplaneindex = -1;
5787         bestplanescore = 1048576.0f;
5788         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5789         {
5790                 if(p->camera_entity == t->camera_entity)
5791                 {
5792                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5793                         if (bestplaneindex < 0 || bestplanescore > planescore)
5794                         {
5795                                 bestplaneindex = planeindex;
5796                                 bestplanescore = planescore;
5797                         }
5798                 }
5799         }
5800         planeindex = bestplaneindex;
5801         p = r_fb.water.waterplanes + planeindex;
5802
5803         // if this surface does not fit any known plane rendered this frame, add one
5804         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5805         {
5806                 // store the new plane
5807                 planeindex = r_fb.water.numwaterplanes++;
5808                 p = r_fb.water.waterplanes + planeindex;
5809                 p->plane = plane;
5810                 // clear materialflags and pvs
5811                 p->materialflags = 0;
5812                 p->pvsvalid = false;
5813                 p->camera_entity = t->camera_entity;
5814                 VectorCopy(mins, p->mins);
5815                 VectorCopy(maxs, p->maxs);
5816         }
5817         else
5818         {
5819                 // merge mins/maxs when we're adding this surface to the plane
5820                 p->mins[0] = min(p->mins[0], mins[0]);
5821                 p->mins[1] = min(p->mins[1], mins[1]);
5822                 p->mins[2] = min(p->mins[2], mins[2]);
5823                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5824                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5825                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5826         }
5827         // merge this surface's materialflags into the waterplane
5828         p->materialflags |= t->currentmaterialflags;
5829         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5830         {
5831                 // merge this surface's PVS into the waterplane
5832                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5833                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5834                 {
5835                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5836                         p->pvsvalid = true;
5837                 }
5838         }
5839 }
5840
5841 extern cvar_t r_drawparticles;
5842 extern cvar_t r_drawdecals;
5843
5844 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5845 {
5846         int myscissor[4];
5847         r_refdef_view_t originalview;
5848         r_refdef_view_t myview;
5849         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;
5850         r_waterstate_waterplane_t *p;
5851         vec3_t visorigin;
5852         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;
5853         char vabuf[1024];
5854
5855         originalview = r_refdef.view;
5856
5857         // lowquality hack, temporarily shut down some cvars and restore afterwards
5858         qualityreduction = r_water_lowquality.integer;
5859         if (qualityreduction > 0)
5860         {
5861                 if (qualityreduction >= 1)
5862                 {
5863                         old_r_shadows = r_shadows.integer;
5864                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5865                         old_r_dlight = r_shadow_realtime_dlight.integer;
5866                         Cvar_SetValueQuick(&r_shadows, 0);
5867                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5868                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5869                 }
5870                 if (qualityreduction >= 2)
5871                 {
5872                         old_r_dynamic = r_dynamic.integer;
5873                         old_r_particles = r_drawparticles.integer;
5874                         old_r_decals = r_drawdecals.integer;
5875                         Cvar_SetValueQuick(&r_dynamic, 0);
5876                         Cvar_SetValueQuick(&r_drawparticles, 0);
5877                         Cvar_SetValueQuick(&r_drawdecals, 0);
5878                 }
5879         }
5880
5881         // make sure enough textures are allocated
5882         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5883         {
5884                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5885                 {
5886                         if (!p->texture_refraction)
5887                                 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);
5888                         if (!p->texture_refraction)
5889                                 goto error;
5890                         if (usewaterfbo)
5891                         {
5892                                 if (r_fb.water.depthtexture == NULL)
5893                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5894                                 if (p->fbo_refraction == 0)
5895                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5896                         }
5897                 }
5898                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5899                 {
5900                         if (!p->texture_camera)
5901                                 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);
5902                         if (!p->texture_camera)
5903                                 goto error;
5904                         if (usewaterfbo)
5905                         {
5906                                 if (r_fb.water.depthtexture == NULL)
5907                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5908                                 if (p->fbo_camera == 0)
5909                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5910                         }
5911                 }
5912
5913                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5914                 {
5915                         if (!p->texture_reflection)
5916                                 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);
5917                         if (!p->texture_reflection)
5918                                 goto error;
5919                         if (usewaterfbo)
5920                         {
5921                                 if (r_fb.water.depthtexture == NULL)
5922                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5923                                 if (p->fbo_reflection == 0)
5924                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5925                         }
5926                 }
5927         }
5928
5929         // render views
5930         r_refdef.view = originalview;
5931         r_refdef.view.showdebug = false;
5932         r_refdef.view.width = r_fb.water.waterwidth;
5933         r_refdef.view.height = r_fb.water.waterheight;
5934         r_refdef.view.useclipplane = true;
5935         myview = r_refdef.view;
5936         r_fb.water.renderingscene = true;
5937         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5938         {
5939                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5940                 {
5941                         r_refdef.view = myview;
5942                         if(r_water_scissormode.integer)
5943                         {
5944                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5945                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5946                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5947                         }
5948
5949                         // render reflected scene and copy into texture
5950                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5951                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5952                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5953                         r_refdef.view.clipplane = p->plane;
5954                         // reverse the cullface settings for this render
5955                         r_refdef.view.cullface_front = GL_FRONT;
5956                         r_refdef.view.cullface_back = GL_BACK;
5957                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5958                         {
5959                                 r_refdef.view.usecustompvs = true;
5960                                 if (p->pvsvalid)
5961                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5962                                 else
5963                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5964                         }
5965
5966                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5967                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5968                         R_ClearScreen(r_refdef.fogenabled);
5969                         if(r_water_scissormode.integer & 2)
5970                                 R_View_UpdateWithScissor(myscissor);
5971                         else
5972                                 R_View_Update();
5973                         R_AnimCache_CacheVisibleEntities();
5974                         if(r_water_scissormode.integer & 1)
5975                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5976                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5977
5978                         if (!p->fbo_reflection)
5979                                 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);
5980                         r_fb.water.hideplayer = false;
5981                 }
5982
5983                 // render the normal view scene and copy into texture
5984                 // (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)
5985                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5986                 {
5987                         r_refdef.view = myview;
5988                         if(r_water_scissormode.integer)
5989                         {
5990                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5991                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5992                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5993                         }
5994
5995                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5996
5997                         r_refdef.view.clipplane = p->plane;
5998                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5999                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6000
6001                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6002                         {
6003                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6004                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6005                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6006                                 R_RenderView_UpdateViewVectors();
6007                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6008                                 {
6009                                         r_refdef.view.usecustompvs = true;
6010                                         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);
6011                                 }
6012                         }
6013
6014                         PlaneClassify(&r_refdef.view.clipplane);
6015
6016                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6017                         R_ClearScreen(r_refdef.fogenabled);
6018                         if(r_water_scissormode.integer & 2)
6019                                 R_View_UpdateWithScissor(myscissor);
6020                         else
6021                                 R_View_Update();
6022                         R_AnimCache_CacheVisibleEntities();
6023                         if(r_water_scissormode.integer & 1)
6024                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6025                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6026
6027                         if (!p->fbo_refraction)
6028                                 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);
6029                         r_fb.water.hideplayer = false;
6030                 }
6031                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6032                 {
6033                         r_refdef.view = myview;
6034
6035                         r_refdef.view.clipplane = p->plane;
6036                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6037                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6038
6039                         r_refdef.view.width = r_fb.water.camerawidth;
6040                         r_refdef.view.height = r_fb.water.cameraheight;
6041                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6042                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6043                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6044                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6045
6046                         if(p->camera_entity)
6047                         {
6048                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6049                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6050                         }
6051
6052                         // note: all of the view is used for displaying... so
6053                         // there is no use in scissoring
6054
6055                         // reverse the cullface settings for this render
6056                         r_refdef.view.cullface_front = GL_FRONT;
6057                         r_refdef.view.cullface_back = GL_BACK;
6058                         // also reverse the view matrix
6059                         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
6060                         R_RenderView_UpdateViewVectors();
6061                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6062                         {
6063                                 r_refdef.view.usecustompvs = true;
6064                                 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);
6065                         }
6066                         
6067                         // camera needs no clipplane
6068                         r_refdef.view.useclipplane = false;
6069
6070                         PlaneClassify(&r_refdef.view.clipplane);
6071
6072                         r_fb.water.hideplayer = false;
6073
6074                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6075                         R_ClearScreen(r_refdef.fogenabled);
6076                         R_View_Update();
6077                         R_AnimCache_CacheVisibleEntities();
6078                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6079
6080                         if (!p->fbo_camera)
6081                                 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);
6082                         r_fb.water.hideplayer = false;
6083                 }
6084
6085         }
6086         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6087         r_fb.water.renderingscene = false;
6088         r_refdef.view = originalview;
6089         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6090         if (!r_fb.water.depthtexture)
6091                 R_ClearScreen(r_refdef.fogenabled);
6092         R_View_Update();
6093         R_AnimCache_CacheVisibleEntities();
6094         goto finish;
6095 error:
6096         r_refdef.view = originalview;
6097         r_fb.water.renderingscene = false;
6098         Cvar_SetValueQuick(&r_water, 0);
6099         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6100 finish:
6101         // lowquality hack, restore cvars
6102         if (qualityreduction > 0)
6103         {
6104                 if (qualityreduction >= 1)
6105                 {
6106                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6107                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6108                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6109                 }
6110                 if (qualityreduction >= 2)
6111                 {
6112                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6113                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6114                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6115                 }
6116         }
6117 }
6118
6119 static void R_Bloom_StartFrame(void)
6120 {
6121         int i;
6122         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6123         int viewwidth, viewheight;
6124         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6125         textype_t textype = TEXTYPE_COLORBUFFER;
6126
6127         switch (vid.renderpath)
6128         {
6129         case RENDERPATH_GL20:
6130                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6131                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6132                 {
6133                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6134                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6135                 }
6136                 break;
6137         case RENDERPATH_GL11:
6138         case RENDERPATH_GL13:
6139         case RENDERPATH_GLES1:
6140         case RENDERPATH_GLES2:
6141         case RENDERPATH_D3D9:
6142         case RENDERPATH_D3D10:
6143         case RENDERPATH_D3D11:
6144                 r_fb.usedepthtextures = false;
6145                 break;
6146         case RENDERPATH_SOFT:
6147                 r_fb.usedepthtextures = true;
6148                 break;
6149         }
6150
6151         if (r_viewscale_fpsscaling.integer)
6152         {
6153                 double actualframetime;
6154                 double targetframetime;
6155                 double adjust;
6156                 actualframetime = r_refdef.lastdrawscreentime;
6157                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6158                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6159                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6160                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6161                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6162                 viewscalefpsadjusted += adjust;
6163                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6164         }
6165         else
6166                 viewscalefpsadjusted = 1.0f;
6167
6168         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6169
6170         switch(vid.renderpath)
6171         {
6172         case RENDERPATH_GL20:
6173         case RENDERPATH_D3D9:
6174         case RENDERPATH_D3D10:
6175         case RENDERPATH_D3D11:
6176         case RENDERPATH_SOFT:
6177         case RENDERPATH_GLES2:
6178                 break;
6179         case RENDERPATH_GL11:
6180         case RENDERPATH_GL13:
6181         case RENDERPATH_GLES1:
6182                 return;
6183         }
6184
6185         // set bloomwidth and bloomheight to the bloom resolution that will be
6186         // used (often less than the screen resolution for faster rendering)
6187         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6188         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6189         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6190         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6191         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6192
6193         // calculate desired texture sizes
6194         if (vid.support.arb_texture_non_power_of_two)
6195         {
6196                 screentexturewidth = vid.width;
6197                 screentextureheight = vid.height;
6198                 bloomtexturewidth = r_fb.bloomwidth;
6199                 bloomtextureheight = r_fb.bloomheight;
6200         }
6201         else
6202         {
6203                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6204                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6205                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6206                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6207         }
6208
6209         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))
6210         {
6211                 Cvar_SetValueQuick(&r_bloom, 0);
6212                 Cvar_SetValueQuick(&r_motionblur, 0);
6213                 Cvar_SetValueQuick(&r_damageblur, 0);
6214         }
6215
6216         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6217          && !r_bloom.integer
6218          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6219          && !useviewfbo
6220          && r_viewscale.value == 1.0f
6221          && !r_viewscale_fpsscaling.integer)
6222                 screentexturewidth = screentextureheight = 0;
6223         if (!r_bloom.integer)
6224                 bloomtexturewidth = bloomtextureheight = 0;
6225
6226         // allocate textures as needed
6227         if (r_fb.screentexturewidth != screentexturewidth
6228          || r_fb.screentextureheight != screentextureheight
6229          || r_fb.bloomtexturewidth != bloomtexturewidth
6230          || r_fb.bloomtextureheight != bloomtextureheight
6231          || r_fb.textype != textype
6232          || useviewfbo != (r_fb.fbo != 0))
6233         {
6234                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6235                 {
6236                         if (r_fb.bloomtexture[i])
6237                                 R_FreeTexture(r_fb.bloomtexture[i]);
6238                         r_fb.bloomtexture[i] = NULL;
6239
6240                         if (r_fb.bloomfbo[i])
6241                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6242                         r_fb.bloomfbo[i] = 0;
6243                 }
6244
6245                 if (r_fb.fbo)
6246                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6247                 r_fb.fbo = 0;
6248
6249                 if (r_fb.colortexture)
6250                         R_FreeTexture(r_fb.colortexture);
6251                 r_fb.colortexture = NULL;
6252
6253                 if (r_fb.depthtexture)
6254                         R_FreeTexture(r_fb.depthtexture);
6255                 r_fb.depthtexture = NULL;
6256
6257                 if (r_fb.ghosttexture)
6258                         R_FreeTexture(r_fb.ghosttexture);
6259                 r_fb.ghosttexture = NULL;
6260
6261                 r_fb.screentexturewidth = screentexturewidth;
6262                 r_fb.screentextureheight = screentextureheight;
6263                 r_fb.bloomtexturewidth = bloomtexturewidth;
6264                 r_fb.bloomtextureheight = bloomtextureheight;
6265                 r_fb.textype = textype;
6266
6267                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6268                 {
6269                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6270                                 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);
6271                         r_fb.ghosttexture_valid = false;
6272                         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);
6273                         if (useviewfbo)
6274                         {
6275                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6276                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6277                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6278                         }
6279                 }
6280
6281                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6282                 {
6283                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6284                         {
6285                                 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);
6286                                 if (useviewfbo)
6287                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6288                         }
6289                 }
6290         }
6291
6292         // bloom texture is a different resolution
6293         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6294         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6295         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6296         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6297         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6298
6299         // set up a texcoord array for the full resolution screen image
6300         // (we have to keep this around to copy back during final render)
6301         r_fb.screentexcoord2f[0] = 0;
6302         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6303         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6304         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6305         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6306         r_fb.screentexcoord2f[5] = 0;
6307         r_fb.screentexcoord2f[6] = 0;
6308         r_fb.screentexcoord2f[7] = 0;
6309
6310         if(r_fb.fbo) 
6311         {
6312                 for (i = 1;i < 8;i += 2)
6313                 {
6314                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6315                 }
6316         }
6317
6318         // set up a texcoord array for the reduced resolution bloom image
6319         // (which will be additive blended over the screen image)
6320         r_fb.bloomtexcoord2f[0] = 0;
6321         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6322         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6323         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6324         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6325         r_fb.bloomtexcoord2f[5] = 0;
6326         r_fb.bloomtexcoord2f[6] = 0;
6327         r_fb.bloomtexcoord2f[7] = 0;
6328
6329         switch(vid.renderpath)
6330         {
6331         case RENDERPATH_GL11:
6332         case RENDERPATH_GL13:
6333         case RENDERPATH_GL20:
6334         case RENDERPATH_SOFT:
6335         case RENDERPATH_GLES1:
6336         case RENDERPATH_GLES2:
6337                 break;
6338         case RENDERPATH_D3D9:
6339         case RENDERPATH_D3D10:
6340         case RENDERPATH_D3D11:
6341                 for (i = 0;i < 4;i++)
6342                 {
6343                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6344                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6345                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6346                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6347                 }
6348                 break;
6349         }
6350
6351         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6352
6353         if (r_fb.fbo)
6354                 r_refdef.view.clear = true;
6355 }
6356
6357 static void R_Bloom_MakeTexture(void)
6358 {
6359         int x, range, dir;
6360         float xoffset, yoffset, r, brighten;
6361         rtexture_t *intex;
6362         float colorscale = r_bloom_colorscale.value;
6363
6364         r_refdef.stats[r_stat_bloom]++;
6365     
6366 #if 0
6367     // this copy is unnecessary since it happens in R_BlendView already
6368         if (!r_fb.fbo)
6369         {
6370                 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);
6371                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6372         }
6373 #endif
6374
6375         // scale down screen texture to the bloom texture size
6376         CHECKGLERROR
6377         r_fb.bloomindex = 0;
6378         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6379         R_SetViewport(&r_fb.bloomviewport);
6380         GL_DepthTest(false);
6381         GL_BlendFunc(GL_ONE, GL_ZERO);
6382         GL_Color(colorscale, colorscale, colorscale, 1);
6383         // 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...
6384         switch(vid.renderpath)
6385         {
6386         case RENDERPATH_GL11:
6387         case RENDERPATH_GL13:
6388         case RENDERPATH_GL20:
6389         case RENDERPATH_GLES1:
6390         case RENDERPATH_GLES2:
6391         case RENDERPATH_SOFT:
6392                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6393                 break;
6394         case RENDERPATH_D3D9:
6395         case RENDERPATH_D3D10:
6396         case RENDERPATH_D3D11:
6397                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6398                 break;
6399         }
6400         // TODO: do boxfilter scale-down in shader?
6401         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6402         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6403         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6404
6405         // we now have a properly scaled bloom image
6406         if (!r_fb.bloomfbo[r_fb.bloomindex])
6407         {
6408                 // copy it into the bloom texture
6409                 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);
6410                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6411         }
6412
6413         // multiply bloom image by itself as many times as desired
6414         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6415         {
6416                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6417                 r_fb.bloomindex ^= 1;
6418                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6419                 x *= 2;
6420                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6421                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6422                 {
6423                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6424                         GL_Color(r,r,r,1); // apply fix factor
6425                 }
6426                 else
6427                 {
6428                         if(x <= 2)
6429                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6430                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6431                         GL_Color(1,1,1,1); // no fix factor supported here
6432                 }
6433                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6434                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6435                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6436                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6437
6438                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6439                 {
6440                         // copy the darkened image to a texture
6441                         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);
6442                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6443                 }
6444         }
6445
6446         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6447         brighten = r_bloom_brighten.value;
6448         brighten = sqrt(brighten);
6449         if(range >= 1)
6450                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6451
6452         for (dir = 0;dir < 2;dir++)
6453         {
6454                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6455                 r_fb.bloomindex ^= 1;
6456                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6457                 // blend on at multiple vertical offsets to achieve a vertical blur
6458                 // TODO: do offset blends using GLSL
6459                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6460                 GL_BlendFunc(GL_ONE, GL_ZERO);
6461                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6462                 for (x = -range;x <= range;x++)
6463                 {
6464                         if (!dir){xoffset = 0;yoffset = x;}
6465                         else {xoffset = x;yoffset = 0;}
6466                         xoffset /= (float)r_fb.bloomtexturewidth;
6467                         yoffset /= (float)r_fb.bloomtextureheight;
6468                         // compute a texcoord array with the specified x and y offset
6469                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6470                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6471                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6472                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6473                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6474                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6475                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6476                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6477                         // this r value looks like a 'dot' particle, fading sharply to
6478                         // black at the edges
6479                         // (probably not realistic but looks good enough)
6480                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6481                         //r = brighten/(range*2+1);
6482                         r = brighten / (range * 2 + 1);
6483                         if(range >= 1)
6484                                 r *= (1 - x*x/(float)(range*range));
6485                         GL_Color(r, r, r, 1);
6486                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6487                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6488                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6489                         GL_BlendFunc(GL_ONE, GL_ONE);
6490                 }
6491
6492                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6493                 {
6494                         // copy the vertically or horizontally blurred bloom view to a texture
6495                         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);
6496                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6497                 }
6498         }
6499 }
6500
6501 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6502 {
6503         unsigned int permutation;
6504         float uservecs[4][4];
6505
6506         R_EntityMatrix(&identitymatrix);
6507
6508         switch (vid.renderpath)
6509         {
6510         case RENDERPATH_GL20:
6511         case RENDERPATH_D3D9:
6512         case RENDERPATH_D3D10:
6513         case RENDERPATH_D3D11:
6514         case RENDERPATH_SOFT:
6515         case RENDERPATH_GLES2:
6516                 permutation =
6517                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6518                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6519                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6520                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6521                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6522
6523                 if (r_fb.colortexture)
6524                 {
6525                         if (!r_fb.fbo)
6526                         {
6527                                 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);
6528                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6529                         }
6530
6531                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6532                         {
6533                                 // declare variables
6534                                 float blur_factor, blur_mouseaccel, blur_velocity;
6535                                 static float blur_average; 
6536                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6537
6538                                 // set a goal for the factoring
6539                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6540                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6541                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6542                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6543                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6544                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6545
6546                                 // from the goal, pick an averaged value between goal and last value
6547                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6548                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6549
6550                                 // enforce minimum amount of blur 
6551                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6552
6553                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6554
6555                                 // calculate values into a standard alpha
6556                                 cl.motionbluralpha = 1 - exp(-
6557                                                 (
6558                                                  (r_motionblur.value * blur_factor / 80)
6559                                                  +
6560                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6561                                                 )
6562                                                 /
6563                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6564                                           );
6565
6566                                 // randomization for the blur value to combat persistent ghosting
6567                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6568                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6569
6570                                 // apply the blur
6571                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6572                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6573                                 {
6574                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6575                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6576                                         switch(vid.renderpath)
6577                                         {
6578                                         case RENDERPATH_GL11:
6579                                         case RENDERPATH_GL13:
6580                                         case RENDERPATH_GL20:
6581                                         case RENDERPATH_GLES1:
6582                                         case RENDERPATH_GLES2:
6583                                         case RENDERPATH_SOFT:
6584                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6585                                                 break;
6586                                         case RENDERPATH_D3D9:
6587                                         case RENDERPATH_D3D10:
6588                                         case RENDERPATH_D3D11:
6589                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6590                                                 break;
6591                                         }
6592                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6593                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6594                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6595                                 }
6596
6597                                 // updates old view angles for next pass
6598                                 VectorCopy(cl.viewangles, blur_oldangles);
6599
6600                                 // copy view into the ghost texture
6601                                 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);
6602                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6603                                 r_fb.ghosttexture_valid = true;
6604                         }
6605                 }
6606                 else
6607                 {
6608                         // no r_fb.colortexture means we're rendering to the real fb
6609                         // we may still have to do view tint...
6610                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6611                         {
6612                                 // apply a color tint to the whole view
6613                                 R_ResetViewRendering2D(0, NULL, NULL);
6614                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6615                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6616                                 R_SetupShader_Generic_NoTexture(false, true);
6617                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6618                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6619                         }
6620                         break; // no screen processing, no bloom, skip it
6621                 }
6622
6623                 if (r_fb.bloomtexture[0])
6624                 {
6625                         // make the bloom texture
6626                         R_Bloom_MakeTexture();
6627                 }
6628
6629 #if _MSC_VER >= 1400
6630 #define sscanf sscanf_s
6631 #endif
6632                 memset(uservecs, 0, sizeof(uservecs));
6633                 if (r_glsl_postprocess_uservec1_enable.integer)
6634                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6635                 if (r_glsl_postprocess_uservec2_enable.integer)
6636                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6637                 if (r_glsl_postprocess_uservec3_enable.integer)
6638                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6639                 if (r_glsl_postprocess_uservec4_enable.integer)
6640                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6641
6642                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6643                 GL_Color(1, 1, 1, 1);
6644                 GL_BlendFunc(GL_ONE, GL_ZERO);
6645
6646                 switch(vid.renderpath)
6647                 {
6648                 case RENDERPATH_GL20:
6649                 case RENDERPATH_GLES2:
6650                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6651                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6652                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6653                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6654                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6655                         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]);
6656                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6657                         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]);
6658                         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]);
6659                         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]);
6660                         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]);
6661                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6662                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6663                         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);
6664                         break;
6665                 case RENDERPATH_D3D9:
6666 #ifdef SUPPORTD3D
6667                         // 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...
6668                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6669                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6670                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6671                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6672                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6673                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6674                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6675                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6676                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6677                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6678                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6679                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6680                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6681                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6682 #endif
6683                         break;
6684                 case RENDERPATH_D3D10:
6685                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6686                         break;
6687                 case RENDERPATH_D3D11:
6688                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6689                         break;
6690                 case RENDERPATH_SOFT:
6691                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6692                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6693                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6694                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6695                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6696                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6697                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6698                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6699                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6700                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6701                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6702                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6703                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6704                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6705                         break;
6706                 default:
6707                         break;
6708                 }
6709                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6710                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6711                 break;
6712         case RENDERPATH_GL11:
6713         case RENDERPATH_GL13:
6714         case RENDERPATH_GLES1:
6715                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6716                 {
6717                         // apply a color tint to the whole view
6718                         R_ResetViewRendering2D(0, NULL, NULL);
6719                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6720                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6721                         R_SetupShader_Generic_NoTexture(false, true);
6722                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6723                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6724                 }
6725                 break;
6726         }
6727 }
6728
6729 matrix4x4_t r_waterscrollmatrix;
6730
6731 void R_UpdateFog(void)
6732 {
6733         // Nehahra fog
6734         if (gamemode == GAME_NEHAHRA)
6735         {
6736                 if (gl_fogenable.integer)
6737                 {
6738                         r_refdef.oldgl_fogenable = true;
6739                         r_refdef.fog_density = gl_fogdensity.value;
6740                         r_refdef.fog_red = gl_fogred.value;
6741                         r_refdef.fog_green = gl_foggreen.value;
6742                         r_refdef.fog_blue = gl_fogblue.value;
6743                         r_refdef.fog_alpha = 1;
6744                         r_refdef.fog_start = 0;
6745                         r_refdef.fog_end = gl_skyclip.value;
6746                         r_refdef.fog_height = 1<<30;
6747                         r_refdef.fog_fadedepth = 128;
6748                 }
6749                 else if (r_refdef.oldgl_fogenable)
6750                 {
6751                         r_refdef.oldgl_fogenable = false;
6752                         r_refdef.fog_density = 0;
6753                         r_refdef.fog_red = 0;
6754                         r_refdef.fog_green = 0;
6755                         r_refdef.fog_blue = 0;
6756                         r_refdef.fog_alpha = 0;
6757                         r_refdef.fog_start = 0;
6758                         r_refdef.fog_end = 0;
6759                         r_refdef.fog_height = 1<<30;
6760                         r_refdef.fog_fadedepth = 128;
6761                 }
6762         }
6763
6764         // fog parms
6765         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6766         r_refdef.fog_start = max(0, r_refdef.fog_start);
6767         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6768
6769         if (r_refdef.fog_density && r_drawfog.integer)
6770         {
6771                 r_refdef.fogenabled = true;
6772                 // this is the point where the fog reaches 0.9986 alpha, which we
6773                 // consider a good enough cutoff point for the texture
6774                 // (0.9986 * 256 == 255.6)
6775                 if (r_fog_exp2.integer)
6776                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6777                 else
6778                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6779                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6780                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6781                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6782                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6783                         R_BuildFogHeightTexture();
6784                 // fog color was already set
6785                 // update the fog texture
6786                 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)
6787                         R_BuildFogTexture();
6788                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6789                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6790         }
6791         else
6792                 r_refdef.fogenabled = false;
6793
6794         // fog color
6795         if (r_refdef.fog_density)
6796         {
6797                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6798                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6799                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6800
6801                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6802                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6803                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6804                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6805
6806                 {
6807                         vec3_t fogvec;
6808                         VectorCopy(r_refdef.fogcolor, fogvec);
6809                         //   color.rgb *= ContrastBoost * SceneBrightness;
6810                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6811                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6812                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6813                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6814                 }
6815         }
6816 }
6817
6818 void R_UpdateVariables(void)
6819 {
6820         R_Textures_Frame();
6821
6822         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6823
6824         r_refdef.farclip = r_farclip_base.value;
6825         if (r_refdef.scene.worldmodel)
6826                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6827         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6828
6829         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6830                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6831         r_refdef.polygonfactor = 0;
6832         r_refdef.polygonoffset = 0;
6833         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6834         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6835
6836         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6837         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6838         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6839         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6840         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6841         if (FAKELIGHT_ENABLED)
6842         {
6843                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6844         }
6845         else if (r_refdef.scene.worldmodel)
6846         {
6847                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6848         }
6849         if (r_showsurfaces.integer)
6850         {
6851                 r_refdef.scene.rtworld = false;
6852                 r_refdef.scene.rtworldshadows = false;
6853                 r_refdef.scene.rtdlight = false;
6854                 r_refdef.scene.rtdlightshadows = false;
6855                 r_refdef.lightmapintensity = 0;
6856         }
6857
6858         switch(vid.renderpath)
6859         {
6860         case RENDERPATH_GL20:
6861         case RENDERPATH_D3D9:
6862         case RENDERPATH_D3D10:
6863         case RENDERPATH_D3D11:
6864         case RENDERPATH_SOFT:
6865         case RENDERPATH_GLES2:
6866                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6867                 {
6868                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6869                         {
6870                                 // build GLSL gamma texture
6871 #define RAMPWIDTH 256
6872                                 unsigned short ramp[RAMPWIDTH * 3];
6873                                 unsigned char rampbgr[RAMPWIDTH][4];
6874                                 int i;
6875
6876                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6877
6878                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6879                                 for(i = 0; i < RAMPWIDTH; ++i)
6880                                 {
6881                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6882                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6883                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6884                                         rampbgr[i][3] = 0;
6885                                 }
6886                                 if (r_texture_gammaramps)
6887                                 {
6888                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6889                                 }
6890                                 else
6891                                 {
6892                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6893                                 }
6894                         }
6895                 }
6896                 else
6897                 {
6898                         // remove GLSL gamma texture
6899                 }
6900                 break;
6901         case RENDERPATH_GL11:
6902         case RENDERPATH_GL13:
6903         case RENDERPATH_GLES1:
6904                 break;
6905         }
6906 }
6907
6908 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6909 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6910 /*
6911 ================
6912 R_SelectScene
6913 ================
6914 */
6915 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6916         if( scenetype != r_currentscenetype ) {
6917                 // store the old scenetype
6918                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6919                 r_currentscenetype = scenetype;
6920                 // move in the new scene
6921                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6922         }
6923 }
6924
6925 /*
6926 ================
6927 R_GetScenePointer
6928 ================
6929 */
6930 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6931 {
6932         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6933         if( scenetype == r_currentscenetype ) {
6934                 return &r_refdef.scene;
6935         } else {
6936                 return &r_scenes_store[ scenetype ];
6937         }
6938 }
6939
6940 static int R_SortEntities_Compare(const void *ap, const void *bp)
6941 {
6942         const entity_render_t *a = *(const entity_render_t **)ap;
6943         const entity_render_t *b = *(const entity_render_t **)bp;
6944
6945         // 1. compare model
6946         if(a->model < b->model)
6947                 return -1;
6948         if(a->model > b->model)
6949                 return +1;
6950
6951         // 2. compare skin
6952         // TODO possibly calculate the REAL skinnum here first using
6953         // skinscenes?
6954         if(a->skinnum < b->skinnum)
6955                 return -1;
6956         if(a->skinnum > b->skinnum)
6957                 return +1;
6958
6959         // everything we compared is equal
6960         return 0;
6961 }
6962 static void R_SortEntities(void)
6963 {
6964         // below or equal 2 ents, sorting never gains anything
6965         if(r_refdef.scene.numentities <= 2)
6966                 return;
6967         // sort
6968         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6969 }
6970
6971 /*
6972 ================
6973 R_RenderView
6974 ================
6975 */
6976 int dpsoftrast_test;
6977 extern cvar_t r_shadow_bouncegrid;
6978 void R_RenderView(void)
6979 {
6980         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6981         int fbo;
6982         rtexture_t *depthtexture;
6983         rtexture_t *colortexture;
6984
6985         dpsoftrast_test = r_test.integer;
6986
6987         if (r_timereport_active)
6988                 R_TimeReport("start");
6989         r_textureframe++; // used only by R_GetCurrentTexture
6990         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6991
6992         if(R_CompileShader_CheckStaticParms())
6993                 R_GLSL_Restart_f();
6994
6995         if (!r_drawentities.integer)
6996                 r_refdef.scene.numentities = 0;
6997         else if (r_sortentities.integer)
6998                 R_SortEntities();
6999
7000         R_AnimCache_ClearCache();
7001         R_FrameData_NewFrame();
7002
7003         /* adjust for stereo display */
7004         if(R_Stereo_Active())
7005         {
7006                 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);
7007                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7008         }
7009
7010         if (r_refdef.view.isoverlay)
7011         {
7012                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7013                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7014                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7015                 R_TimeReport("depthclear");
7016
7017                 r_refdef.view.showdebug = false;
7018
7019                 r_fb.water.enabled = false;
7020                 r_fb.water.numwaterplanes = 0;
7021
7022                 R_RenderScene(0, NULL, NULL);
7023
7024                 r_refdef.view.matrix = originalmatrix;
7025
7026                 CHECKGLERROR
7027                 return;
7028         }
7029
7030         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7031         {
7032                 r_refdef.view.matrix = originalmatrix;
7033                 return;
7034         }
7035
7036         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7037
7038         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7039                 // in sRGB fallback, behave similar to true sRGB: convert this
7040                 // value from linear to sRGB
7041                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7042
7043         R_RenderView_UpdateViewVectors();
7044
7045         R_Shadow_UpdateWorldLightSelection();
7046
7047         R_Bloom_StartFrame();
7048
7049         // apply bloom brightness offset
7050         if(r_fb.bloomtexture[0])
7051                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7052
7053         R_Water_StartFrame();
7054
7055         // now we probably have an fbo to render into
7056         fbo = r_fb.fbo;
7057         depthtexture = r_fb.depthtexture;
7058         colortexture = r_fb.colortexture;
7059
7060         CHECKGLERROR
7061         if (r_timereport_active)
7062                 R_TimeReport("viewsetup");
7063
7064         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7065
7066         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7067         {
7068                 R_ClearScreen(r_refdef.fogenabled);
7069                 if (r_timereport_active)
7070                         R_TimeReport("viewclear");
7071         }
7072         r_refdef.view.clear = true;
7073
7074         r_refdef.view.showdebug = true;
7075
7076         R_View_Update();
7077         if (r_timereport_active)
7078                 R_TimeReport("visibility");
7079
7080         R_AnimCache_CacheVisibleEntities();
7081         if (r_timereport_active)
7082                 R_TimeReport("animcache");
7083
7084         R_Shadow_UpdateBounceGridTexture();
7085         if (r_timereport_active && r_shadow_bouncegrid.integer)
7086                 R_TimeReport("bouncegrid");
7087
7088         r_fb.water.numwaterplanes = 0;
7089         if (r_fb.water.enabled)
7090                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7091
7092         R_RenderScene(fbo, depthtexture, colortexture);
7093         r_fb.water.numwaterplanes = 0;
7094
7095         R_BlendView(fbo, depthtexture, colortexture);
7096         if (r_timereport_active)
7097                 R_TimeReport("blendview");
7098
7099         GL_Scissor(0, 0, vid.width, vid.height);
7100         GL_ScissorTest(false);
7101
7102         r_refdef.view.matrix = originalmatrix;
7103
7104         CHECKGLERROR
7105 }
7106
7107 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7108 {
7109         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7110         {
7111                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7112                 if (r_timereport_active)
7113                         R_TimeReport("waterworld");
7114         }
7115
7116         // don't let sound skip if going slow
7117         if (r_refdef.scene.extraupdate)
7118                 S_ExtraUpdate ();
7119
7120         R_DrawModelsAddWaterPlanes();
7121         if (r_timereport_active)
7122                 R_TimeReport("watermodels");
7123
7124         if (r_fb.water.numwaterplanes)
7125         {
7126                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7127                 if (r_timereport_active)
7128                         R_TimeReport("waterscenes");
7129         }
7130 }
7131
7132 extern cvar_t cl_locs_show;
7133 static void R_DrawLocs(void);
7134 static void R_DrawEntityBBoxes(void);
7135 static void R_DrawModelDecals(void);
7136 extern cvar_t cl_decals_newsystem;
7137 extern qboolean r_shadow_usingdeferredprepass;
7138 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7139 {
7140         qboolean shadowmapping = false;
7141
7142         if (r_timereport_active)
7143                 R_TimeReport("beginscene");
7144
7145         r_refdef.stats[r_stat_renders]++;
7146
7147         R_UpdateFog();
7148
7149         // don't let sound skip if going slow
7150         if (r_refdef.scene.extraupdate)
7151                 S_ExtraUpdate ();
7152
7153         R_MeshQueue_BeginScene();
7154
7155         R_SkyStartFrame();
7156
7157         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);
7158
7159         if (r_timereport_active)
7160                 R_TimeReport("skystartframe");
7161
7162         if (cl.csqc_vidvars.drawworld)
7163         {
7164                 // don't let sound skip if going slow
7165                 if (r_refdef.scene.extraupdate)
7166                         S_ExtraUpdate ();
7167
7168                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7169                 {
7170                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7171                         if (r_timereport_active)
7172                                 R_TimeReport("worldsky");
7173                 }
7174
7175                 if (R_DrawBrushModelsSky() && r_timereport_active)
7176                         R_TimeReport("bmodelsky");
7177
7178                 if (skyrendermasked && skyrenderlater)
7179                 {
7180                         // we have to force off the water clipping plane while rendering sky
7181                         R_SetupView(false, fbo, depthtexture, colortexture);
7182                         R_Sky();
7183                         R_SetupView(true, fbo, depthtexture, colortexture);
7184                         if (r_timereport_active)
7185                                 R_TimeReport("sky");
7186                 }
7187         }
7188
7189         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7190         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7191                 R_Shadow_PrepareModelShadows();
7192         if (r_timereport_active)
7193                 R_TimeReport("preparelights");
7194
7195         if (R_Shadow_ShadowMappingEnabled())
7196                 shadowmapping = true;
7197
7198         if (r_shadow_usingdeferredprepass)
7199                 R_Shadow_DrawPrepass();
7200
7201         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7202         {
7203                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7204                 if (r_timereport_active)
7205                         R_TimeReport("worlddepth");
7206         }
7207         if (r_depthfirst.integer >= 2)
7208         {
7209                 R_DrawModelsDepth();
7210                 if (r_timereport_active)
7211                         R_TimeReport("modeldepth");
7212         }
7213
7214         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7215         {
7216                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7217                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7218                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7219                 // don't let sound skip if going slow
7220                 if (r_refdef.scene.extraupdate)
7221                         S_ExtraUpdate ();
7222         }
7223
7224         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7225         {
7226                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7227                 if (r_timereport_active)
7228                         R_TimeReport("world");
7229         }
7230
7231         // don't let sound skip if going slow
7232         if (r_refdef.scene.extraupdate)
7233                 S_ExtraUpdate ();
7234
7235         R_DrawModels();
7236         if (r_timereport_active)
7237                 R_TimeReport("models");
7238
7239         // don't let sound skip if going slow
7240         if (r_refdef.scene.extraupdate)
7241                 S_ExtraUpdate ();
7242
7243         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7244         {
7245                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7246                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7247                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7248                 // don't let sound skip if going slow
7249                 if (r_refdef.scene.extraupdate)
7250                         S_ExtraUpdate ();
7251         }
7252
7253         if (!r_shadow_usingdeferredprepass)
7254         {
7255                 R_Shadow_DrawLights();
7256                 if (r_timereport_active)
7257                         R_TimeReport("rtlights");
7258         }
7259
7260         // don't let sound skip if going slow
7261         if (r_refdef.scene.extraupdate)
7262                 S_ExtraUpdate ();
7263
7264         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7265         {
7266                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7267                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7268                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7269                 // don't let sound skip if going slow
7270                 if (r_refdef.scene.extraupdate)
7271                         S_ExtraUpdate ();
7272         }
7273
7274         if (cl.csqc_vidvars.drawworld)
7275         {
7276                 if (cl_decals_newsystem.integer)
7277                 {
7278                         R_DrawModelDecals();
7279                         if (r_timereport_active)
7280                                 R_TimeReport("modeldecals");
7281                 }
7282                 else
7283                 {
7284                         R_DrawDecals();
7285                         if (r_timereport_active)
7286                                 R_TimeReport("decals");
7287                 }
7288
7289                 R_DrawParticles();
7290                 if (r_timereport_active)
7291                         R_TimeReport("particles");
7292
7293                 R_DrawExplosions();
7294                 if (r_timereport_active)
7295                         R_TimeReport("explosions");
7296
7297                 R_DrawLightningBeams();
7298                 if (r_timereport_active)
7299                         R_TimeReport("lightning");
7300         }
7301
7302         if (cl.csqc_loaded)
7303                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7304
7305         if (r_refdef.view.showdebug)
7306         {
7307                 if (cl_locs_show.integer)
7308                 {
7309                         R_DrawLocs();
7310                         if (r_timereport_active)
7311                                 R_TimeReport("showlocs");
7312                 }
7313
7314                 if (r_drawportals.integer)
7315                 {
7316                         R_DrawPortals();
7317                         if (r_timereport_active)
7318                                 R_TimeReport("portals");
7319                 }
7320
7321                 if (r_showbboxes.value > 0)
7322                 {
7323                         R_DrawEntityBBoxes();
7324                         if (r_timereport_active)
7325                                 R_TimeReport("bboxes");
7326                 }
7327         }
7328
7329         if (r_transparent.integer)
7330         {
7331                 R_MeshQueue_RenderTransparent();
7332                 if (r_timereport_active)
7333                         R_TimeReport("drawtrans");
7334         }
7335
7336         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))
7337         {
7338                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7339                 if (r_timereport_active)
7340                         R_TimeReport("worlddebug");
7341                 R_DrawModelsDebug();
7342                 if (r_timereport_active)
7343                         R_TimeReport("modeldebug");
7344         }
7345
7346         if (cl.csqc_vidvars.drawworld)
7347         {
7348                 R_Shadow_DrawCoronas();
7349                 if (r_timereport_active)
7350                         R_TimeReport("coronas");
7351         }
7352
7353 #if 0
7354         {
7355                 GL_DepthTest(false);
7356                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7357                 GL_Color(1, 1, 1, 1);
7358                 qglBegin(GL_POLYGON);
7359                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7360                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7361                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7362                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7363                 qglEnd();
7364                 qglBegin(GL_POLYGON);
7365                 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]);
7366                 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]);
7367                 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]);
7368                 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]);
7369                 qglEnd();
7370                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7371         }
7372 #endif
7373
7374         // don't let sound skip if going slow
7375         if (r_refdef.scene.extraupdate)
7376                 S_ExtraUpdate ();
7377 }
7378
7379 static const unsigned short bboxelements[36] =
7380 {
7381         5, 1, 3, 5, 3, 7,
7382         6, 2, 0, 6, 0, 4,
7383         7, 3, 2, 7, 2, 6,
7384         4, 0, 1, 4, 1, 5,
7385         4, 5, 7, 4, 7, 6,
7386         1, 0, 2, 1, 2, 3,
7387 };
7388
7389 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7390 {
7391         int i;
7392         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7393
7394         RSurf_ActiveWorldEntity();
7395
7396         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7397         GL_DepthMask(false);
7398         GL_DepthRange(0, 1);
7399         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7400 //      R_Mesh_ResetTextureState();
7401
7402         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7403         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7404         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7405         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7406         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7407         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7408         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7409         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7410         R_FillColors(color4f, 8, cr, cg, cb, ca);
7411         if (r_refdef.fogenabled)
7412         {
7413                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7414                 {
7415                         f1 = RSurf_FogVertex(v);
7416                         f2 = 1 - f1;
7417                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7418                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7419                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7420                 }
7421         }
7422         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7423         R_Mesh_ResetTextureState();
7424         R_SetupShader_Generic_NoTexture(false, false);
7425         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7426 }
7427
7428 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7429 {
7430         prvm_prog_t *prog = SVVM_prog;
7431         int i;
7432         float color[4];
7433         prvm_edict_t *edict;
7434
7435         // this function draws bounding boxes of server entities
7436         if (!sv.active)
7437                 return;
7438
7439         GL_CullFace(GL_NONE);
7440         R_SetupShader_Generic_NoTexture(false, false);
7441
7442         for (i = 0;i < numsurfaces;i++)
7443         {
7444                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7445                 switch ((int)PRVM_serveredictfloat(edict, solid))
7446                 {
7447                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7448                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7449                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7450                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7451                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7452                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7453                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7454                 }
7455                 color[3] *= r_showbboxes.value;
7456                 color[3] = bound(0, color[3], 1);
7457                 GL_DepthTest(!r_showdisabledepthtest.integer);
7458                 GL_CullFace(r_refdef.view.cullface_front);
7459                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7460         }
7461 }
7462
7463 static void R_DrawEntityBBoxes(void)
7464 {
7465         int i;
7466         prvm_edict_t *edict;
7467         vec3_t center;
7468         prvm_prog_t *prog = SVVM_prog;
7469
7470         // this function draws bounding boxes of server entities
7471         if (!sv.active)
7472                 return;
7473
7474         for (i = 0;i < prog->num_edicts;i++)
7475         {
7476                 edict = PRVM_EDICT_NUM(i);
7477                 if (edict->priv.server->free)
7478                         continue;
7479                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7480                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7481                         continue;
7482                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7483                         continue;
7484                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7485                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7486         }
7487 }
7488
7489 static const int nomodelelement3i[24] =
7490 {
7491         5, 2, 0,
7492         5, 1, 2,
7493         5, 0, 3,
7494         5, 3, 1,
7495         0, 2, 4,
7496         2, 1, 4,
7497         3, 0, 4,
7498         1, 3, 4
7499 };
7500
7501 static const unsigned short nomodelelement3s[24] =
7502 {
7503         5, 2, 0,
7504         5, 1, 2,
7505         5, 0, 3,
7506         5, 3, 1,
7507         0, 2, 4,
7508         2, 1, 4,
7509         3, 0, 4,
7510         1, 3, 4
7511 };
7512
7513 static const float nomodelvertex3f[6*3] =
7514 {
7515         -16,   0,   0,
7516          16,   0,   0,
7517           0, -16,   0,
7518           0,  16,   0,
7519           0,   0, -16,
7520           0,   0,  16
7521 };
7522
7523 static const float nomodelcolor4f[6*4] =
7524 {
7525         0.0f, 0.0f, 0.5f, 1.0f,
7526         0.0f, 0.0f, 0.5f, 1.0f,
7527         0.0f, 0.5f, 0.0f, 1.0f,
7528         0.0f, 0.5f, 0.0f, 1.0f,
7529         0.5f, 0.0f, 0.0f, 1.0f,
7530         0.5f, 0.0f, 0.0f, 1.0f
7531 };
7532
7533 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7534 {
7535         int i;
7536         float f1, f2, *c;
7537         float color4f[6*4];
7538
7539         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);
7540
7541         // this is only called once per entity so numsurfaces is always 1, and
7542         // surfacelist is always {0}, so this code does not handle batches
7543
7544         if (rsurface.ent_flags & RENDER_ADDITIVE)
7545         {
7546                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7547                 GL_DepthMask(false);
7548         }
7549         else if (rsurface.colormod[3] < 1)
7550         {
7551                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7552                 GL_DepthMask(false);
7553         }
7554         else
7555         {
7556                 GL_BlendFunc(GL_ONE, GL_ZERO);
7557                 GL_DepthMask(true);
7558         }
7559         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7560         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7561         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7562         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7563         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7564         for (i = 0, c = color4f;i < 6;i++, c += 4)
7565         {
7566                 c[0] *= rsurface.colormod[0];
7567                 c[1] *= rsurface.colormod[1];
7568                 c[2] *= rsurface.colormod[2];
7569                 c[3] *= rsurface.colormod[3];
7570         }
7571         if (r_refdef.fogenabled)
7572         {
7573                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7574                 {
7575                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7576                         f2 = 1 - f1;
7577                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7578                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7579                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7580                 }
7581         }
7582 //      R_Mesh_ResetTextureState();
7583         R_SetupShader_Generic_NoTexture(false, false);
7584         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7585         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7586 }
7587
7588 void R_DrawNoModel(entity_render_t *ent)
7589 {
7590         vec3_t org;
7591         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7592         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7593                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7594         else
7595                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7596 }
7597
7598 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7599 {
7600         vec3_t right1, right2, diff, normal;
7601
7602         VectorSubtract (org2, org1, normal);
7603
7604         // calculate 'right' vector for start
7605         VectorSubtract (r_refdef.view.origin, org1, diff);
7606         CrossProduct (normal, diff, right1);
7607         VectorNormalize (right1);
7608
7609         // calculate 'right' vector for end
7610         VectorSubtract (r_refdef.view.origin, org2, diff);
7611         CrossProduct (normal, diff, right2);
7612         VectorNormalize (right2);
7613
7614         vert[ 0] = org1[0] + width * right1[0];
7615         vert[ 1] = org1[1] + width * right1[1];
7616         vert[ 2] = org1[2] + width * right1[2];
7617         vert[ 3] = org1[0] - width * right1[0];
7618         vert[ 4] = org1[1] - width * right1[1];
7619         vert[ 5] = org1[2] - width * right1[2];
7620         vert[ 6] = org2[0] - width * right2[0];
7621         vert[ 7] = org2[1] - width * right2[1];
7622         vert[ 8] = org2[2] - width * right2[2];
7623         vert[ 9] = org2[0] + width * right2[0];
7624         vert[10] = org2[1] + width * right2[1];
7625         vert[11] = org2[2] + width * right2[2];
7626 }
7627
7628 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)
7629 {
7630         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7631         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7632         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7633         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7634         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7635         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7636         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7637         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7638         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7639         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7640         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7641         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7642 }
7643
7644 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7645 {
7646         int i;
7647         float *vertex3f;
7648         float v[3];
7649         VectorSet(v, x, y, z);
7650         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7651                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7652                         break;
7653         if (i == mesh->numvertices)
7654         {
7655                 if (mesh->numvertices < mesh->maxvertices)
7656                 {
7657                         VectorCopy(v, vertex3f);
7658                         mesh->numvertices++;
7659                 }
7660                 return mesh->numvertices;
7661         }
7662         else
7663                 return i;
7664 }
7665
7666 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7667 {
7668         int i;
7669         int *e, element[3];
7670         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7671         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7672         e = mesh->element3i + mesh->numtriangles * 3;
7673         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7674         {
7675                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7676                 if (mesh->numtriangles < mesh->maxtriangles)
7677                 {
7678                         *e++ = element[0];
7679                         *e++ = element[1];
7680                         *e++ = element[2];
7681                         mesh->numtriangles++;
7682                 }
7683                 element[1] = element[2];
7684         }
7685 }
7686
7687 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7688 {
7689         int i;
7690         int *e, element[3];
7691         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7692         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7693         e = mesh->element3i + mesh->numtriangles * 3;
7694         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7695         {
7696                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7697                 if (mesh->numtriangles < mesh->maxtriangles)
7698                 {
7699                         *e++ = element[0];
7700                         *e++ = element[1];
7701                         *e++ = element[2];
7702                         mesh->numtriangles++;
7703                 }
7704                 element[1] = element[2];
7705         }
7706 }
7707
7708 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7709 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7710 {
7711         int planenum, planenum2;
7712         int w;
7713         int tempnumpoints;
7714         mplane_t *plane, *plane2;
7715         double maxdist;
7716         double temppoints[2][256*3];
7717         // figure out how large a bounding box we need to properly compute this brush
7718         maxdist = 0;
7719         for (w = 0;w < numplanes;w++)
7720                 maxdist = max(maxdist, fabs(planes[w].dist));
7721         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7722         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7723         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7724         {
7725                 w = 0;
7726                 tempnumpoints = 4;
7727                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7728                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7729                 {
7730                         if (planenum2 == planenum)
7731                                 continue;
7732                         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);
7733                         w = !w;
7734                 }
7735                 if (tempnumpoints < 3)
7736                         continue;
7737                 // generate elements forming a triangle fan for this polygon
7738                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7739         }
7740 }
7741
7742 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)
7743 {
7744         texturelayer_t *layer;
7745         layer = t->currentlayers + t->currentnumlayers++;
7746         layer->type = type;
7747         layer->depthmask = depthmask;
7748         layer->blendfunc1 = blendfunc1;
7749         layer->blendfunc2 = blendfunc2;
7750         layer->texture = texture;
7751         layer->texmatrix = *matrix;
7752         layer->color[0] = r;
7753         layer->color[1] = g;
7754         layer->color[2] = b;
7755         layer->color[3] = a;
7756 }
7757
7758 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7759 {
7760         if(parms[0] == 0 && parms[1] == 0)
7761                 return false;
7762         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7763                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7764                         return false;
7765         return true;
7766 }
7767
7768 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7769 {
7770         double index, f;
7771         index = parms[2] + rsurface.shadertime * parms[3];
7772         index -= floor(index);
7773         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7774         {
7775         default:
7776         case Q3WAVEFUNC_NONE:
7777         case Q3WAVEFUNC_NOISE:
7778         case Q3WAVEFUNC_COUNT:
7779                 f = 0;
7780                 break;
7781         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7782         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7783         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7784         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7785         case Q3WAVEFUNC_TRIANGLE:
7786                 index *= 4;
7787                 f = index - floor(index);
7788                 if (index < 1)
7789                 {
7790                         // f = f;
7791                 }
7792                 else if (index < 2)
7793                         f = 1 - f;
7794                 else if (index < 3)
7795                         f = -f;
7796                 else
7797                         f = -(1 - f);
7798                 break;
7799         }
7800         f = parms[0] + parms[1] * f;
7801         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7802                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7803         return (float) f;
7804 }
7805
7806 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7807 {
7808         int w, h, idx;
7809         double f;
7810         double offsetd[2];
7811         float tcmat[12];
7812         matrix4x4_t matrix, temp;
7813         switch(tcmod->tcmod)
7814         {
7815                 case Q3TCMOD_COUNT:
7816                 case Q3TCMOD_NONE:
7817                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7818                                 matrix = r_waterscrollmatrix;
7819                         else
7820                                 matrix = identitymatrix;
7821                         break;
7822                 case Q3TCMOD_ENTITYTRANSLATE:
7823                         // this is used in Q3 to allow the gamecode to control texcoord
7824                         // scrolling on the entity, which is not supported in darkplaces yet.
7825                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7826                         break;
7827                 case Q3TCMOD_ROTATE:
7828                         f = tcmod->parms[0] * rsurface.shadertime;
7829                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7830                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7831                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7832                         break;
7833                 case Q3TCMOD_SCALE:
7834                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7835                         break;
7836                 case Q3TCMOD_SCROLL:
7837                         // extra care is needed because of precision breakdown with large values of time
7838                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7839                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7840                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7841                         break;
7842                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7843                         w = (int) tcmod->parms[0];
7844                         h = (int) tcmod->parms[1];
7845                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7846                         f = f - floor(f);
7847                         idx = (int) floor(f * w * h);
7848                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7849                         break;
7850                 case Q3TCMOD_STRETCH:
7851                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7852                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7853                         break;
7854                 case Q3TCMOD_TRANSFORM:
7855                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7856                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7857                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7858                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7859                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7860                         break;
7861                 case Q3TCMOD_TURBULENT:
7862                         // this is handled in the RSurf_PrepareVertices function
7863                         matrix = identitymatrix;
7864                         break;
7865         }
7866         temp = *texmatrix;
7867         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7868 }
7869
7870 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7871 {
7872         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7873         char name[MAX_QPATH];
7874         skinframe_t *skinframe;
7875         unsigned char pixels[296*194];
7876         strlcpy(cache->name, skinname, sizeof(cache->name));
7877         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7878         if (developer_loading.integer)
7879                 Con_Printf("loading %s\n", name);
7880         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7881         if (!skinframe || !skinframe->base)
7882         {
7883                 unsigned char *f;
7884                 fs_offset_t filesize;
7885                 skinframe = NULL;
7886                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7887                 if (f)
7888                 {
7889                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7890                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7891                         Mem_Free(f);
7892                 }
7893         }
7894         cache->skinframe = skinframe;
7895 }
7896
7897 texture_t *R_GetCurrentTexture(texture_t *t)
7898 {
7899         int i;
7900         const entity_render_t *ent = rsurface.entity;
7901         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7902         q3shaderinfo_layer_tcmod_t *tcmod;
7903
7904         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7905                 return t->currentframe;
7906         t->update_lastrenderframe = r_textureframe;
7907         t->update_lastrenderentity = (void *)ent;
7908
7909         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7910                 t->camera_entity = ent->entitynumber;
7911         else
7912                 t->camera_entity = 0;
7913
7914         // switch to an alternate material if this is a q1bsp animated material
7915         {
7916                 texture_t *texture = t;
7917                 int s = rsurface.ent_skinnum;
7918                 if ((unsigned int)s >= (unsigned int)model->numskins)
7919                         s = 0;
7920                 if (model->skinscenes)
7921                 {
7922                         if (model->skinscenes[s].framecount > 1)
7923                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7924                         else
7925                                 s = model->skinscenes[s].firstframe;
7926                 }
7927                 if (s > 0)
7928                         t = t + s * model->num_surfaces;
7929                 if (t->animated)
7930                 {
7931                         // use an alternate animation if the entity's frame is not 0,
7932                         // and only if the texture has an alternate animation
7933                         if (rsurface.ent_alttextures && t->anim_total[1])
7934                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7935                         else
7936                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7937                 }
7938                 texture->currentframe = t;
7939         }
7940
7941         // update currentskinframe to be a qw skin or animation frame
7942         if (rsurface.ent_qwskin >= 0)
7943         {
7944                 i = rsurface.ent_qwskin;
7945                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7946                 {
7947                         r_qwskincache_size = cl.maxclients;
7948                         if (r_qwskincache)
7949                                 Mem_Free(r_qwskincache);
7950                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7951                 }
7952                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7953                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7954                 t->currentskinframe = r_qwskincache[i].skinframe;
7955                 if (t->currentskinframe == NULL)
7956                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7957         }
7958         else if (t->numskinframes >= 2)
7959                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7960         if (t->backgroundnumskinframes >= 2)
7961                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7962
7963         t->currentmaterialflags = t->basematerialflags;
7964         t->currentalpha = rsurface.colormod[3];
7965         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7966                 t->currentalpha *= r_wateralpha.value;
7967         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7968                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7969         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7970                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7971         if (!(rsurface.ent_flags & RENDER_LIGHT))
7972                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7973         else if (FAKELIGHT_ENABLED)
7974         {
7975                 // no modellight if using fakelight for the map
7976         }
7977         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7978         {
7979                 // pick a model lighting mode
7980                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7981                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7982                 else
7983                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7984         }
7985         if (rsurface.ent_flags & RENDER_ADDITIVE)
7986                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7987         else if (t->currentalpha < 1)
7988                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7989         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7990         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7991                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7992         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7993                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7994         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7995                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7996         if (t->backgroundnumskinframes)
7997                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7998         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7999         {
8000                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8001                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8002         }
8003         else
8004                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8005         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8006         {
8007                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8008                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8009         }
8010         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8011                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8012
8013         // there is no tcmod
8014         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8015         {
8016                 t->currenttexmatrix = r_waterscrollmatrix;
8017                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8018         }
8019         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8020         {
8021                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8022                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8023         }
8024
8025         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8026                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8027         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8028                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8029
8030         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8031         if (t->currentskinframe->qpixels)
8032                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8033         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8034         if (!t->basetexture)
8035                 t->basetexture = r_texture_notexture;
8036         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8037         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8038         t->nmaptexture = t->currentskinframe->nmap;
8039         if (!t->nmaptexture)
8040                 t->nmaptexture = r_texture_blanknormalmap;
8041         t->glosstexture = r_texture_black;
8042         t->glowtexture = t->currentskinframe->glow;
8043         t->fogtexture = t->currentskinframe->fog;
8044         t->reflectmasktexture = t->currentskinframe->reflect;
8045         if (t->backgroundnumskinframes)
8046         {
8047                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8048                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8049                 t->backgroundglosstexture = r_texture_black;
8050                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8051                 if (!t->backgroundnmaptexture)
8052                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8053                 // make sure that if glow is going to be used, both textures are not NULL
8054                 if (!t->backgroundglowtexture && t->glowtexture)
8055                         t->backgroundglowtexture = r_texture_black;
8056                 if (!t->glowtexture && t->backgroundglowtexture)
8057                         t->glowtexture = r_texture_black;
8058         }
8059         else
8060         {
8061                 t->backgroundbasetexture = r_texture_white;
8062                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8063                 t->backgroundglosstexture = r_texture_black;
8064                 t->backgroundglowtexture = NULL;
8065         }
8066         t->specularpower = r_shadow_glossexponent.value;
8067         // TODO: store reference values for these in the texture?
8068         t->specularscale = 0;
8069         if (r_shadow_gloss.integer > 0)
8070         {
8071                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8072                 {
8073                         if (r_shadow_glossintensity.value > 0)
8074                         {
8075                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8076                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8077                                 t->specularscale = r_shadow_glossintensity.value;
8078                         }
8079                 }
8080                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8081                 {
8082                         t->glosstexture = r_texture_white;
8083                         t->backgroundglosstexture = r_texture_white;
8084                         t->specularscale = r_shadow_gloss2intensity.value;
8085                         t->specularpower = r_shadow_gloss2exponent.value;
8086                 }
8087         }
8088         t->specularscale *= t->specularscalemod;
8089         t->specularpower *= t->specularpowermod;
8090         t->rtlightambient = 0;
8091
8092         // lightmaps mode looks bad with dlights using actual texturing, so turn
8093         // off the colormap and glossmap, but leave the normalmap on as it still
8094         // accurately represents the shading involved
8095         if (gl_lightmaps.integer)
8096         {
8097                 t->basetexture = r_texture_grey128;
8098                 t->pantstexture = r_texture_black;
8099                 t->shirttexture = r_texture_black;
8100                 if (gl_lightmaps.integer < 2)
8101                         t->nmaptexture = r_texture_blanknormalmap;
8102                 t->glosstexture = r_texture_black;
8103                 t->glowtexture = NULL;
8104                 t->fogtexture = NULL;
8105                 t->reflectmasktexture = NULL;
8106                 t->backgroundbasetexture = NULL;
8107                 if (gl_lightmaps.integer < 2)
8108                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8109                 t->backgroundglosstexture = r_texture_black;
8110                 t->backgroundglowtexture = NULL;
8111                 t->specularscale = 0;
8112                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8113         }
8114
8115         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8116         VectorClear(t->dlightcolor);
8117         t->currentnumlayers = 0;
8118         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8119         {
8120                 int blendfunc1, blendfunc2;
8121                 qboolean depthmask;
8122                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8123                 {
8124                         blendfunc1 = GL_SRC_ALPHA;
8125                         blendfunc2 = GL_ONE;
8126                 }
8127                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8128                 {
8129                         blendfunc1 = GL_SRC_ALPHA;
8130                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8131                 }
8132                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8133                 {
8134                         blendfunc1 = t->customblendfunc[0];
8135                         blendfunc2 = t->customblendfunc[1];
8136                 }
8137                 else
8138                 {
8139                         blendfunc1 = GL_ONE;
8140                         blendfunc2 = GL_ZERO;
8141                 }
8142                 // don't colormod evilblend textures
8143                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8144                         VectorSet(t->lightmapcolor, 1, 1, 1);
8145                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8146                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8147                 {
8148                         // fullbright is not affected by r_refdef.lightmapintensity
8149                         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]);
8150                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8151                                 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]);
8152                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8153                                 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]);
8154                 }
8155                 else
8156                 {
8157                         vec3_t ambientcolor;
8158                         float colorscale;
8159                         // set the color tint used for lights affecting this surface
8160                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8161                         colorscale = 2;
8162                         // q3bsp has no lightmap updates, so the lightstylevalue that
8163                         // would normally be baked into the lightmap must be
8164                         // applied to the color
8165                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8166                         if (model->type == mod_brushq3)
8167                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8168                         colorscale *= r_refdef.lightmapintensity;
8169                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8170                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8171                         // basic lit geometry
8172                         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]);
8173                         // add pants/shirt if needed
8174                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8175                                 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]);
8176                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8177                                 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]);
8178                         // now add ambient passes if needed
8179                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8180                         {
8181                                 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]);
8182                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8183                                         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]);
8184                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8185                                         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]);
8186                         }
8187                 }
8188                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8189                         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]);
8190                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8191                 {
8192                         // if this is opaque use alpha blend which will darken the earlier
8193                         // passes cheaply.
8194                         //
8195                         // if this is an alpha blended material, all the earlier passes
8196                         // were darkened by fog already, so we only need to add the fog
8197                         // color ontop through the fog mask texture
8198                         //
8199                         // if this is an additive blended material, all the earlier passes
8200                         // were darkened by fog already, and we should not add fog color
8201                         // (because the background was not darkened, there is no fog color
8202                         // that was lost behind it).
8203                         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]);
8204                 }
8205         }
8206
8207         return t->currentframe;
8208 }
8209
8210 rsurfacestate_t rsurface;
8211
8212 void RSurf_ActiveWorldEntity(void)
8213 {
8214         dp_model_t *model = r_refdef.scene.worldmodel;
8215         //if (rsurface.entity == r_refdef.scene.worldentity)
8216         //      return;
8217         rsurface.entity = r_refdef.scene.worldentity;
8218         rsurface.skeleton = NULL;
8219         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8220         rsurface.ent_skinnum = 0;
8221         rsurface.ent_qwskin = -1;
8222         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8223         rsurface.shadertime = r_refdef.scene.time;
8224         rsurface.matrix = identitymatrix;
8225         rsurface.inversematrix = identitymatrix;
8226         rsurface.matrixscale = 1;
8227         rsurface.inversematrixscale = 1;
8228         R_EntityMatrix(&identitymatrix);
8229         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8230         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8231         rsurface.fograngerecip = r_refdef.fograngerecip;
8232         rsurface.fogheightfade = r_refdef.fogheightfade;
8233         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8234         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8235         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8236         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8237         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8238         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8239         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8240         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8241         rsurface.colormod[3] = 1;
8242         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);
8243         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8244         rsurface.frameblend[0].lerp = 1;
8245         rsurface.ent_alttextures = false;
8246         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8247         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8248         rsurface.entityskeletaltransform3x4 = NULL;
8249         rsurface.entityskeletalnumtransforms = 0;
8250         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8251         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8252         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8253         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8254         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8255         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8256         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8257         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8258         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8259         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8260         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8261         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8262         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8263         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8264         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8265         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8266         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8267         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8268         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8269         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8270         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8271         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8272         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8273         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8274         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8275         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8276         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8277         rsurface.modelelement3i = model->surfmesh.data_element3i;
8278         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8279         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8280         rsurface.modelelement3s = model->surfmesh.data_element3s;
8281         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8282         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8283         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8284         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8285         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8286         rsurface.modelsurfaces = model->data_surfaces;
8287         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8288         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8289         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8290         rsurface.modelgeneratedvertex = false;
8291         rsurface.batchgeneratedvertex = false;
8292         rsurface.batchfirstvertex = 0;
8293         rsurface.batchnumvertices = 0;
8294         rsurface.batchfirsttriangle = 0;
8295         rsurface.batchnumtriangles = 0;
8296         rsurface.batchvertex3f  = NULL;
8297         rsurface.batchvertex3f_vertexbuffer = NULL;
8298         rsurface.batchvertex3f_bufferoffset = 0;
8299         rsurface.batchsvector3f = NULL;
8300         rsurface.batchsvector3f_vertexbuffer = NULL;
8301         rsurface.batchsvector3f_bufferoffset = 0;
8302         rsurface.batchtvector3f = NULL;
8303         rsurface.batchtvector3f_vertexbuffer = NULL;
8304         rsurface.batchtvector3f_bufferoffset = 0;
8305         rsurface.batchnormal3f  = NULL;
8306         rsurface.batchnormal3f_vertexbuffer = NULL;
8307         rsurface.batchnormal3f_bufferoffset = 0;
8308         rsurface.batchlightmapcolor4f = NULL;
8309         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8310         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8311         rsurface.batchtexcoordtexture2f = NULL;
8312         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8313         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8314         rsurface.batchtexcoordlightmap2f = NULL;
8315         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8316         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8317         rsurface.batchskeletalindex4ub = NULL;
8318         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8319         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8320         rsurface.batchskeletalweight4ub = NULL;
8321         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8322         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8323         rsurface.batchvertexmesh = NULL;
8324         rsurface.batchvertexmeshbuffer = NULL;
8325         rsurface.batchvertex3fbuffer = NULL;
8326         rsurface.batchelement3i = NULL;
8327         rsurface.batchelement3i_indexbuffer = NULL;
8328         rsurface.batchelement3i_bufferoffset = 0;
8329         rsurface.batchelement3s = NULL;
8330         rsurface.batchelement3s_indexbuffer = NULL;
8331         rsurface.batchelement3s_bufferoffset = 0;
8332         rsurface.passcolor4f = NULL;
8333         rsurface.passcolor4f_vertexbuffer = NULL;
8334         rsurface.passcolor4f_bufferoffset = 0;
8335         rsurface.forcecurrenttextureupdate = false;
8336 }
8337
8338 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8339 {
8340         dp_model_t *model = ent->model;
8341         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8342         //      return;
8343         rsurface.entity = (entity_render_t *)ent;
8344         rsurface.skeleton = ent->skeleton;
8345         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8346         rsurface.ent_skinnum = ent->skinnum;
8347         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;
8348         rsurface.ent_flags = ent->flags;
8349         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8350         rsurface.matrix = ent->matrix;
8351         rsurface.inversematrix = ent->inversematrix;
8352         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8353         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8354         R_EntityMatrix(&rsurface.matrix);
8355         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8356         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8357         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8358         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8359         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8360         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8361         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8362         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8363         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8364         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8365         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8366         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8367         rsurface.colormod[3] = ent->alpha;
8368         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8369         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8370         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8371         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8372         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8373         if (ent->model->brush.submodel && !prepass)
8374         {
8375                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8376                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8377         }
8378         // if the animcache code decided it should use the shader path, skip the deform step
8379         rsurface.entityskeletaltransform3x4 = ent->animcache_vertex3f ? NULL : ent->animcache_skeletaltransform3x4;
8380         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8381         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8382         {
8383                 if (ent->animcache_vertex3f)
8384                 {
8385                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8386                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8387                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8388                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8389                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8390                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8391                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8392                 }
8393                 else if (wanttangents)
8394                 {
8395                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8396                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8397                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8398                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8399                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8400                         rsurface.modelvertexmesh = NULL;
8401                         rsurface.modelvertexmeshbuffer = NULL;
8402                         rsurface.modelvertex3fbuffer = NULL;
8403                 }
8404                 else if (wantnormals)
8405                 {
8406                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8407                         rsurface.modelsvector3f = NULL;
8408                         rsurface.modeltvector3f = NULL;
8409                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8410                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8411                         rsurface.modelvertexmesh = NULL;
8412                         rsurface.modelvertexmeshbuffer = NULL;
8413                         rsurface.modelvertex3fbuffer = NULL;
8414                 }
8415                 else
8416                 {
8417                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8418                         rsurface.modelsvector3f = NULL;
8419                         rsurface.modeltvector3f = NULL;
8420                         rsurface.modelnormal3f = NULL;
8421                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8422                         rsurface.modelvertexmesh = NULL;
8423                         rsurface.modelvertexmeshbuffer = NULL;
8424                         rsurface.modelvertex3fbuffer = NULL;
8425                 }
8426                 rsurface.modelvertex3f_vertexbuffer = 0;
8427                 rsurface.modelvertex3f_bufferoffset = 0;
8428                 rsurface.modelsvector3f_vertexbuffer = 0;
8429                 rsurface.modelsvector3f_bufferoffset = 0;
8430                 rsurface.modeltvector3f_vertexbuffer = 0;
8431                 rsurface.modeltvector3f_bufferoffset = 0;
8432                 rsurface.modelnormal3f_vertexbuffer = 0;
8433                 rsurface.modelnormal3f_bufferoffset = 0;
8434                 rsurface.modelgeneratedvertex = true;
8435         }
8436         else
8437         {
8438                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8439                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8440                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8441                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8442                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8443                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8444                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8445                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8446                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8447                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8448                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8449                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8450                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8451                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8452                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8453                 rsurface.modelgeneratedvertex = false;
8454         }
8455         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8456         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8457         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8458         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8459         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8460         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8461         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8462         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8463         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8464         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8465         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8466         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8467         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8468         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8469         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8470         rsurface.modelelement3i = model->surfmesh.data_element3i;
8471         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8472         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8473         rsurface.modelelement3s = model->surfmesh.data_element3s;
8474         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8475         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8476         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8477         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8478         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8479         rsurface.modelsurfaces = model->data_surfaces;
8480         rsurface.batchgeneratedvertex = false;
8481         rsurface.batchfirstvertex = 0;
8482         rsurface.batchnumvertices = 0;
8483         rsurface.batchfirsttriangle = 0;
8484         rsurface.batchnumtriangles = 0;
8485         rsurface.batchvertex3f  = NULL;
8486         rsurface.batchvertex3f_vertexbuffer = NULL;
8487         rsurface.batchvertex3f_bufferoffset = 0;
8488         rsurface.batchsvector3f = NULL;
8489         rsurface.batchsvector3f_vertexbuffer = NULL;
8490         rsurface.batchsvector3f_bufferoffset = 0;
8491         rsurface.batchtvector3f = NULL;
8492         rsurface.batchtvector3f_vertexbuffer = NULL;
8493         rsurface.batchtvector3f_bufferoffset = 0;
8494         rsurface.batchnormal3f  = NULL;
8495         rsurface.batchnormal3f_vertexbuffer = NULL;
8496         rsurface.batchnormal3f_bufferoffset = 0;
8497         rsurface.batchlightmapcolor4f = NULL;
8498         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8499         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8500         rsurface.batchtexcoordtexture2f = NULL;
8501         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8502         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8503         rsurface.batchtexcoordlightmap2f = NULL;
8504         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8505         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8506         rsurface.batchskeletalindex4ub = NULL;
8507         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8508         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8509         rsurface.batchskeletalweight4ub = NULL;
8510         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8511         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8512         rsurface.batchvertexmesh = NULL;
8513         rsurface.batchvertexmeshbuffer = NULL;
8514         rsurface.batchvertex3fbuffer = NULL;
8515         rsurface.batchelement3i = NULL;
8516         rsurface.batchelement3i_indexbuffer = NULL;
8517         rsurface.batchelement3i_bufferoffset = 0;
8518         rsurface.batchelement3s = NULL;
8519         rsurface.batchelement3s_indexbuffer = NULL;
8520         rsurface.batchelement3s_bufferoffset = 0;
8521         rsurface.passcolor4f = NULL;
8522         rsurface.passcolor4f_vertexbuffer = NULL;
8523         rsurface.passcolor4f_bufferoffset = 0;
8524         rsurface.forcecurrenttextureupdate = false;
8525 }
8526
8527 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)
8528 {
8529         rsurface.entity = r_refdef.scene.worldentity;
8530         rsurface.skeleton = NULL;
8531         rsurface.ent_skinnum = 0;
8532         rsurface.ent_qwskin = -1;
8533         rsurface.ent_flags = entflags;
8534         rsurface.shadertime = r_refdef.scene.time - shadertime;
8535         rsurface.modelnumvertices = numvertices;
8536         rsurface.modelnumtriangles = numtriangles;
8537         rsurface.matrix = *matrix;
8538         rsurface.inversematrix = *inversematrix;
8539         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8540         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8541         R_EntityMatrix(&rsurface.matrix);
8542         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8543         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8544         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8545         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8546         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8547         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8548         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8549         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8550         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8551         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8552         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8553         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8554         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);
8555         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8556         rsurface.frameblend[0].lerp = 1;
8557         rsurface.ent_alttextures = false;
8558         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8559         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8560         rsurface.entityskeletaltransform3x4 = NULL;
8561         rsurface.entityskeletalnumtransforms = 0;
8562         if (wanttangents)
8563         {
8564                 rsurface.modelvertex3f = (float *)vertex3f;
8565                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8566                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8567                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8568         }
8569         else if (wantnormals)
8570         {
8571                 rsurface.modelvertex3f = (float *)vertex3f;
8572                 rsurface.modelsvector3f = NULL;
8573                 rsurface.modeltvector3f = NULL;
8574                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8575         }
8576         else
8577         {
8578                 rsurface.modelvertex3f = (float *)vertex3f;
8579                 rsurface.modelsvector3f = NULL;
8580                 rsurface.modeltvector3f = NULL;
8581                 rsurface.modelnormal3f = NULL;
8582         }
8583         rsurface.modelvertexmesh = NULL;
8584         rsurface.modelvertexmeshbuffer = NULL;
8585         rsurface.modelvertex3fbuffer = NULL;
8586         rsurface.modelvertex3f_vertexbuffer = 0;
8587         rsurface.modelvertex3f_bufferoffset = 0;
8588         rsurface.modelsvector3f_vertexbuffer = 0;
8589         rsurface.modelsvector3f_bufferoffset = 0;
8590         rsurface.modeltvector3f_vertexbuffer = 0;
8591         rsurface.modeltvector3f_bufferoffset = 0;
8592         rsurface.modelnormal3f_vertexbuffer = 0;
8593         rsurface.modelnormal3f_bufferoffset = 0;
8594         rsurface.modelgeneratedvertex = true;
8595         rsurface.modellightmapcolor4f  = (float *)color4f;
8596         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8597         rsurface.modellightmapcolor4f_bufferoffset = 0;
8598         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8599         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8600         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8601         rsurface.modeltexcoordlightmap2f  = NULL;
8602         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8603         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8604         rsurface.modelskeletalindex4ub = NULL;
8605         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8606         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8607         rsurface.modelskeletalweight4ub = NULL;
8608         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8609         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8610         rsurface.modelelement3i = (int *)element3i;
8611         rsurface.modelelement3i_indexbuffer = NULL;
8612         rsurface.modelelement3i_bufferoffset = 0;
8613         rsurface.modelelement3s = (unsigned short *)element3s;
8614         rsurface.modelelement3s_indexbuffer = NULL;
8615         rsurface.modelelement3s_bufferoffset = 0;
8616         rsurface.modellightmapoffsets = NULL;
8617         rsurface.modelsurfaces = NULL;
8618         rsurface.batchgeneratedvertex = false;
8619         rsurface.batchfirstvertex = 0;
8620         rsurface.batchnumvertices = 0;
8621         rsurface.batchfirsttriangle = 0;
8622         rsurface.batchnumtriangles = 0;
8623         rsurface.batchvertex3f  = NULL;
8624         rsurface.batchvertex3f_vertexbuffer = NULL;
8625         rsurface.batchvertex3f_bufferoffset = 0;
8626         rsurface.batchsvector3f = NULL;
8627         rsurface.batchsvector3f_vertexbuffer = NULL;
8628         rsurface.batchsvector3f_bufferoffset = 0;
8629         rsurface.batchtvector3f = NULL;
8630         rsurface.batchtvector3f_vertexbuffer = NULL;
8631         rsurface.batchtvector3f_bufferoffset = 0;
8632         rsurface.batchnormal3f  = NULL;
8633         rsurface.batchnormal3f_vertexbuffer = NULL;
8634         rsurface.batchnormal3f_bufferoffset = 0;
8635         rsurface.batchlightmapcolor4f = NULL;
8636         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8637         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8638         rsurface.batchtexcoordtexture2f = NULL;
8639         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8640         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8641         rsurface.batchtexcoordlightmap2f = NULL;
8642         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8643         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8644         rsurface.batchskeletalindex4ub = NULL;
8645         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8646         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8647         rsurface.batchskeletalweight4ub = NULL;
8648         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8649         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8650         rsurface.batchvertexmesh = NULL;
8651         rsurface.batchvertexmeshbuffer = NULL;
8652         rsurface.batchvertex3fbuffer = NULL;
8653         rsurface.batchelement3i = NULL;
8654         rsurface.batchelement3i_indexbuffer = NULL;
8655         rsurface.batchelement3i_bufferoffset = 0;
8656         rsurface.batchelement3s = NULL;
8657         rsurface.batchelement3s_indexbuffer = NULL;
8658         rsurface.batchelement3s_bufferoffset = 0;
8659         rsurface.passcolor4f = NULL;
8660         rsurface.passcolor4f_vertexbuffer = NULL;
8661         rsurface.passcolor4f_bufferoffset = 0;
8662         rsurface.forcecurrenttextureupdate = true;
8663
8664         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8665         {
8666                 if ((wantnormals || wanttangents) && !normal3f)
8667                 {
8668                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8669                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8670                 }
8671                 if (wanttangents && !svector3f)
8672                 {
8673                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8674                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8675                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8676                 }
8677         }
8678 }
8679
8680 float RSurf_FogPoint(const float *v)
8681 {
8682         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8683         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8684         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8685         float FogHeightFade = r_refdef.fogheightfade;
8686         float fogfrac;
8687         unsigned int fogmasktableindex;
8688         if (r_refdef.fogplaneviewabove)
8689                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8690         else
8691                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8692         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8693         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8694 }
8695
8696 float RSurf_FogVertex(const float *v)
8697 {
8698         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8699         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8700         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8701         float FogHeightFade = rsurface.fogheightfade;
8702         float fogfrac;
8703         unsigned int fogmasktableindex;
8704         if (r_refdef.fogplaneviewabove)
8705                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8706         else
8707                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8708         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8709         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8710 }
8711
8712 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8713 {
8714         int i;
8715         for (i = 0;i < numelements;i++)
8716                 outelement3i[i] = inelement3i[i] + adjust;
8717 }
8718
8719 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8720 extern cvar_t gl_vbo;
8721 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8722 {
8723         int deformindex;
8724         int firsttriangle;
8725         int numtriangles;
8726         int firstvertex;
8727         int endvertex;
8728         int numvertices;
8729         int surfacefirsttriangle;
8730         int surfacenumtriangles;
8731         int surfacefirstvertex;
8732         int surfaceendvertex;
8733         int surfacenumvertices;
8734         int batchnumsurfaces = texturenumsurfaces;
8735         int batchnumvertices;
8736         int batchnumtriangles;
8737         int needsupdate;
8738         int i, j;
8739         qboolean gaps;
8740         qboolean dynamicvertex;
8741         float amplitude;
8742         float animpos;
8743         float scale;
8744         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8745         float waveparms[4];
8746         unsigned char *ub;
8747         q3shaderinfo_deform_t *deform;
8748         const msurface_t *surface, *firstsurface;
8749         r_vertexmesh_t *vertexmesh;
8750         if (!texturenumsurfaces)
8751                 return;
8752         // find vertex range of this surface batch
8753         gaps = false;
8754         firstsurface = texturesurfacelist[0];
8755         firsttriangle = firstsurface->num_firsttriangle;
8756         batchnumvertices = 0;
8757         batchnumtriangles = 0;
8758         firstvertex = endvertex = firstsurface->num_firstvertex;
8759         for (i = 0;i < texturenumsurfaces;i++)
8760         {
8761                 surface = texturesurfacelist[i];
8762                 if (surface != firstsurface + i)
8763                         gaps = true;
8764                 surfacefirstvertex = surface->num_firstvertex;
8765                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8766                 surfacenumvertices = surface->num_vertices;
8767                 surfacenumtriangles = surface->num_triangles;
8768                 if (firstvertex > surfacefirstvertex)
8769                         firstvertex = surfacefirstvertex;
8770                 if (endvertex < surfaceendvertex)
8771                         endvertex = surfaceendvertex;
8772                 batchnumvertices += surfacenumvertices;
8773                 batchnumtriangles += surfacenumtriangles;
8774         }
8775
8776         r_refdef.stats[r_stat_batch_batches]++;
8777         if (gaps)
8778                 r_refdef.stats[r_stat_batch_withgaps]++;
8779         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8780         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8781         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8782
8783         // we now know the vertex range used, and if there are any gaps in it
8784         rsurface.batchfirstvertex = firstvertex;
8785         rsurface.batchnumvertices = endvertex - firstvertex;
8786         rsurface.batchfirsttriangle = firsttriangle;
8787         rsurface.batchnumtriangles = batchnumtriangles;
8788
8789         // this variable holds flags for which properties have been updated that
8790         // may require regenerating vertexmesh array...
8791         needsupdate = 0;
8792
8793         // check if any dynamic vertex processing must occur
8794         dynamicvertex = false;
8795
8796         // a cvar to force the dynamic vertex path to be taken, for debugging
8797         if (r_batch_debugdynamicvertexpath.integer)
8798         {
8799                 if (!dynamicvertex)
8800                 {
8801                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8802                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8803                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8804                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8805                 }
8806                 dynamicvertex = true;
8807         }
8808
8809         // if there is a chance of animated vertex colors, it's a dynamic batch
8810         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8811         {
8812                 if (!dynamicvertex)
8813                 {
8814                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
8815                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
8816                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
8817                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
8818                 }
8819                 dynamicvertex = true;
8820                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8821         }
8822
8823         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8824         {
8825                 switch (deform->deform)
8826                 {
8827                 default:
8828                 case Q3DEFORM_PROJECTIONSHADOW:
8829                 case Q3DEFORM_TEXT0:
8830                 case Q3DEFORM_TEXT1:
8831                 case Q3DEFORM_TEXT2:
8832                 case Q3DEFORM_TEXT3:
8833                 case Q3DEFORM_TEXT4:
8834                 case Q3DEFORM_TEXT5:
8835                 case Q3DEFORM_TEXT6:
8836                 case Q3DEFORM_TEXT7:
8837                 case Q3DEFORM_NONE:
8838                         break;
8839                 case Q3DEFORM_AUTOSPRITE:
8840                         if (!dynamicvertex)
8841                         {
8842                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
8843                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
8844                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
8845                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
8846                         }
8847                         dynamicvertex = true;
8848                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8849                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8850                         break;
8851                 case Q3DEFORM_AUTOSPRITE2:
8852                         if (!dynamicvertex)
8853                         {
8854                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
8855                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
8856                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
8857                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
8858                         }
8859                         dynamicvertex = true;
8860                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8861                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8862                         break;
8863                 case Q3DEFORM_NORMAL:
8864                         if (!dynamicvertex)
8865                         {
8866                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
8867                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
8868                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
8869                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
8870                         }
8871                         dynamicvertex = true;
8872                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8873                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8874                         break;
8875                 case Q3DEFORM_WAVE:
8876                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8877                                 break; // if wavefunc is a nop, ignore this transform
8878                         if (!dynamicvertex)
8879                         {
8880                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
8881                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
8882                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
8883                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
8884                         }
8885                         dynamicvertex = true;
8886                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8887                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8888                         break;
8889                 case Q3DEFORM_BULGE:
8890                         if (!dynamicvertex)
8891                         {
8892                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
8893                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
8894                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
8895                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
8896                         }
8897                         dynamicvertex = true;
8898                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8899                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8900                         break;
8901                 case Q3DEFORM_MOVE:
8902                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8903                                 break; // if wavefunc is a nop, ignore this transform
8904                         if (!dynamicvertex)
8905                         {
8906                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
8907                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
8908                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
8909                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
8910                         }
8911                         dynamicvertex = true;
8912                         batchneed |= BATCHNEED_ARRAY_VERTEX;
8913                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8914                         break;
8915                 }
8916         }
8917         switch(rsurface.texture->tcgen.tcgen)
8918         {
8919         default:
8920         case Q3TCGEN_TEXTURE:
8921                 break;
8922         case Q3TCGEN_LIGHTMAP:
8923                 if (!dynamicvertex)
8924                 {
8925                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
8926                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
8927                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
8928                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
8929                 }
8930                 dynamicvertex = true;
8931                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8932                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8933                 break;
8934         case Q3TCGEN_VECTOR:
8935                 if (!dynamicvertex)
8936                 {
8937                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
8938                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
8939                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
8940                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
8941                 }
8942                 dynamicvertex = true;
8943                 batchneed |= BATCHNEED_ARRAY_VERTEX;
8944                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8945                 break;
8946         case Q3TCGEN_ENVIRONMENT:
8947                 if (!dynamicvertex)
8948                 {
8949                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
8950                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
8951                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
8952                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
8953                 }
8954                 dynamicvertex = true;
8955                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
8956                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8957                 break;
8958         }
8959         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8960         {
8961                 if (!dynamicvertex)
8962                 {
8963                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
8964                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
8965                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
8966                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
8967                 }
8968                 dynamicvertex = true;
8969                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8970                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8971         }
8972
8973         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8974         {
8975                 if (!dynamicvertex)
8976                 {
8977                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
8978                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
8979                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
8980                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
8981                 }
8982                 dynamicvertex = true;
8983                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8984         }
8985
8986         // when the model data has no vertex buffer (dynamic mesh), we need to
8987         // eliminate gaps
8988         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8989                 batchneed |= BATCHNEED_NOGAPS;
8990
8991         // the caller can specify BATCHNEED_NOGAPS to force a batch with
8992         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
8993         // we ensure this by treating the vertex batch as dynamic...
8994         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
8995         {
8996                 if (!dynamicvertex)
8997                 {
8998                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
8999                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9000                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9001                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9002                 }
9003                 dynamicvertex = true;
9004         }
9005
9006         if (dynamicvertex)
9007         {
9008                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9009                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9010                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9011                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9012                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9013                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9014                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9015                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9016         }
9017
9018         // if needsupdate, we have to do a dynamic vertex batch for sure
9019         if (needsupdate & batchneed)
9020         {
9021                 if (!dynamicvertex)
9022                 {
9023                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9024                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9025                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9026                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9027                 }
9028                 dynamicvertex = true;
9029         }
9030
9031         // see if we need to build vertexmesh from arrays
9032         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9033         {
9034                 if (!dynamicvertex)
9035                 {
9036                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9037                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9038                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9039                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9040                 }
9041                 dynamicvertex = true;
9042         }
9043
9044         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9045         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9046                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9047
9048         rsurface.batchvertex3f = rsurface.modelvertex3f;
9049         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9050         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9051         rsurface.batchsvector3f = rsurface.modelsvector3f;
9052         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9053         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9054         rsurface.batchtvector3f = rsurface.modeltvector3f;
9055         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9056         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9057         rsurface.batchnormal3f = rsurface.modelnormal3f;
9058         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9059         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9060         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9061         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9062         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9063         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9064         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9065         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9066         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9067         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9068         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9069         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9070         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9071         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9072         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9073         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9074         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9075         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
9076         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9077         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
9078         rsurface.batchelement3i = rsurface.modelelement3i;
9079         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9080         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9081         rsurface.batchelement3s = rsurface.modelelement3s;
9082         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9083         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9084         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9085         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9086
9087         // if any dynamic vertex processing has to occur in software, we copy the
9088         // entire surface list together before processing to rebase the vertices
9089         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9090         //
9091         // if any gaps exist and we do not have a static vertex buffer, we have to
9092         // copy the surface list together to avoid wasting upload bandwidth on the
9093         // vertices in the gaps.
9094         //
9095         // if gaps exist and we have a static vertex buffer, we can choose whether
9096         // to combine the index buffer ranges into one dynamic index buffer or
9097         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9098         //
9099         // in many cases the batch is reduced to one draw call.
9100
9101         rsurface.batchmultidraw = false;
9102         rsurface.batchmultidrawnumsurfaces = 0;
9103         rsurface.batchmultidrawsurfacelist = NULL;
9104
9105         if (!dynamicvertex)
9106         {
9107                 // static vertex data, just set pointers...
9108                 rsurface.batchgeneratedvertex = false;
9109                 // if there are gaps, we want to build a combined index buffer,
9110                 // otherwise use the original static buffer with an appropriate offset
9111                 if (gaps)
9112                 {
9113                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9114                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9115                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9116                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9117                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9118                         {
9119                                 rsurface.batchmultidraw = true;
9120                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9121                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9122                                 return;
9123                         }
9124                         // build a new triangle elements array for this batch
9125                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9126                         rsurface.batchfirsttriangle = 0;
9127                         numtriangles = 0;
9128                         for (i = 0;i < texturenumsurfaces;i++)
9129                         {
9130                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9131                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9132                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9133                                 numtriangles += surfacenumtriangles;
9134                         }
9135                         rsurface.batchelement3i_indexbuffer = NULL;
9136                         rsurface.batchelement3i_bufferoffset = 0;
9137                         rsurface.batchelement3s = NULL;
9138                         rsurface.batchelement3s_indexbuffer = NULL;
9139                         rsurface.batchelement3s_bufferoffset = 0;
9140                         if (endvertex <= 65536)
9141                         {
9142                                 // make a 16bit (unsigned short) index array if possible
9143                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9144                                 for (i = 0;i < numtriangles*3;i++)
9145                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9146                         }
9147                 }
9148                 else
9149                 {
9150                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9151                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9152                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9153                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9154                 }
9155                 return;
9156         }
9157
9158         // something needs software processing, do it for real...
9159         // we only directly handle separate array data in this case and then
9160         // generate interleaved data if needed...
9161         rsurface.batchgeneratedvertex = true;
9162         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9163         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9164         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9165         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9166
9167         // now copy the vertex data into a combined array and make an index array
9168         // (this is what Quake3 does all the time)
9169         // we also apply any skeletal animation here that would have been done in
9170         // the vertex shader, because most of the dynamic vertex animation cases
9171         // need actual vertex positions and normals
9172         //if (dynamicvertex)
9173         {
9174                 rsurface.batchvertex3fbuffer = NULL;
9175                 rsurface.batchvertexmesh = NULL;
9176                 rsurface.batchvertexmeshbuffer = NULL;
9177                 rsurface.batchvertex3f = NULL;
9178                 rsurface.batchvertex3f_vertexbuffer = NULL;
9179                 rsurface.batchvertex3f_bufferoffset = 0;
9180                 rsurface.batchsvector3f = NULL;
9181                 rsurface.batchsvector3f_vertexbuffer = NULL;
9182                 rsurface.batchsvector3f_bufferoffset = 0;
9183                 rsurface.batchtvector3f = NULL;
9184                 rsurface.batchtvector3f_vertexbuffer = NULL;
9185                 rsurface.batchtvector3f_bufferoffset = 0;
9186                 rsurface.batchnormal3f = NULL;
9187                 rsurface.batchnormal3f_vertexbuffer = NULL;
9188                 rsurface.batchnormal3f_bufferoffset = 0;
9189                 rsurface.batchlightmapcolor4f = NULL;
9190                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9191                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9192                 rsurface.batchtexcoordtexture2f = NULL;
9193                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9194                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9195                 rsurface.batchtexcoordlightmap2f = NULL;
9196                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9197                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9198                 rsurface.batchskeletalindex4ub = NULL;
9199                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9200                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9201                 rsurface.batchskeletalweight4ub = NULL;
9202                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9203                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9204                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9205                 rsurface.batchelement3i_indexbuffer = NULL;
9206                 rsurface.batchelement3i_bufferoffset = 0;
9207                 rsurface.batchelement3s = NULL;
9208                 rsurface.batchelement3s_indexbuffer = NULL;
9209                 rsurface.batchelement3s_bufferoffset = 0;
9210                 // we'll only be setting up certain arrays as needed
9211                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9212                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9213                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9214                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9215                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9216                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9217                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9218                 {
9219                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9220                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9221                 }
9222                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9223                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9224                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9225                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9226                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9227                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9228                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9229                 {
9230                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9231                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9232                 }
9233                 numvertices = 0;
9234                 numtriangles = 0;
9235                 for (i = 0;i < texturenumsurfaces;i++)
9236                 {
9237                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9238                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9239                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9240                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9241                         // copy only the data requested
9242                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9243                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9244                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9245                         {
9246                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9247                                 {
9248                                         if (rsurface.batchvertex3f)
9249                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9250                                         else
9251                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9252                                 }
9253                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9254                                 {
9255                                         if (rsurface.modelnormal3f)
9256                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9257                                         else
9258                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9259                                 }
9260                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9261                                 {
9262                                         if (rsurface.modelsvector3f)
9263                                         {
9264                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9265                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9266                                         }
9267                                         else
9268                                         {
9269                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9270                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9271                                         }
9272                                 }
9273                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9274                                 {
9275                                         if (rsurface.modellightmapcolor4f)
9276                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9277                                         else
9278                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9279                                 }
9280                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9281                                 {
9282                                         if (rsurface.modeltexcoordtexture2f)
9283                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9284                                         else
9285                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9286                                 }
9287                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9288                                 {
9289                                         if (rsurface.modeltexcoordlightmap2f)
9290                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9291                                         else
9292                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9293                                 }
9294                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9295                                 {
9296                                         if (rsurface.modelskeletalindex4ub)
9297                                         {
9298                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9299                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9300                                         }
9301                                         else
9302                                         {
9303                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9304                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9305                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9306                                                 for (j = 0;j < surfacenumvertices;j++)
9307                                                         ub[j*4] = 255;
9308                                         }
9309                                 }
9310                         }
9311                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9312                         numvertices += surfacenumvertices;
9313                         numtriangles += surfacenumtriangles;
9314                 }
9315
9316                 // generate a 16bit index array as well if possible
9317                 // (in general, dynamic batches fit)
9318                 if (numvertices <= 65536)
9319                 {
9320                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9321                         for (i = 0;i < numtriangles*3;i++)
9322                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9323                 }
9324
9325                 // since we've copied everything, the batch now starts at 0
9326                 rsurface.batchfirstvertex = 0;
9327                 rsurface.batchnumvertices = batchnumvertices;
9328                 rsurface.batchfirsttriangle = 0;
9329                 rsurface.batchnumtriangles = batchnumtriangles;
9330         }
9331
9332         // apply skeletal animation that would have been done in the vertex shader
9333         if (rsurface.batchskeletaltransform3x4)
9334         {
9335                 const unsigned char *si;
9336                 const unsigned char *sw;
9337                 const float *t[4];
9338                 const float *b = rsurface.batchskeletaltransform3x4;
9339                 float *vp, *vs, *vt, *vn;
9340                 float w[4];
9341                 float m[3][4], n[3][4];
9342                 float tp[3], ts[3], tt[3], tn[3];
9343                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9344                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9345                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9346                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9347                 si = rsurface.batchskeletalindex4ub;
9348                 sw = rsurface.batchskeletalweight4ub;
9349                 vp = rsurface.batchvertex3f;
9350                 vs = rsurface.batchsvector3f;
9351                 vt = rsurface.batchtvector3f;
9352                 vn = rsurface.batchnormal3f;
9353                 memset(m[0], 0, sizeof(m));
9354                 memset(n[0], 0, sizeof(n));
9355                 for (i = 0;i < batchnumvertices;i++)
9356                 {
9357                         t[0] = b + si[0]*12;
9358                         if (sw[0] == 255)
9359                         {
9360                                 // common case - only one matrix
9361                                 m[0][0] = t[0][ 0];
9362                                 m[0][1] = t[0][ 1];
9363                                 m[0][2] = t[0][ 2];
9364                                 m[0][3] = t[0][ 3];
9365                                 m[1][0] = t[0][ 4];
9366                                 m[1][1] = t[0][ 5];
9367                                 m[1][2] = t[0][ 6];
9368                                 m[1][3] = t[0][ 7];
9369                                 m[2][0] = t[0][ 8];
9370                                 m[2][1] = t[0][ 9];
9371                                 m[2][2] = t[0][10];
9372                                 m[2][3] = t[0][11];
9373                         }
9374                         else if (sw[2] + sw[3])
9375                         {
9376                                 // blend 4 matrices
9377                                 t[1] = b + si[1]*12;
9378                                 t[2] = b + si[2]*12;
9379                                 t[3] = b + si[3]*12;
9380                                 w[0] = sw[0] * (1.0f / 255.0f);
9381                                 w[1] = sw[1] * (1.0f / 255.0f);
9382                                 w[2] = sw[2] * (1.0f / 255.0f);
9383                                 w[3] = sw[3] * (1.0f / 255.0f);
9384                                 // blend the matrices
9385                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9386                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9387                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9388                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9389                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9390                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9391                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9392                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9393                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9394                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9395                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9396                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9397                         }
9398                         else
9399                         {
9400                                 // blend 2 matrices
9401                                 t[1] = b + si[1]*12;
9402                                 w[0] = sw[0] * (1.0f / 255.0f);
9403                                 w[1] = sw[1] * (1.0f / 255.0f);
9404                                 // blend the matrices
9405                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9406                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9407                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9408                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9409                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9410                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9411                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9412                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9413                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9414                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9415                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9416                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9417                         }
9418                         si += 4;
9419                         sw += 4;
9420                         // modify the vertex
9421                         VectorCopy(vp, tp);
9422                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9423                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9424                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9425                         vp += 3;
9426                         if (vn)
9427                         {
9428                                 // the normal transformation matrix is a set of cross products...
9429                                 CrossProduct(m[1], m[2], n[0]);
9430                                 CrossProduct(m[2], m[0], n[1]);
9431                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9432                                 VectorCopy(vn, tn);
9433                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9434                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9435                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9436                                 VectorNormalize(vn);
9437                                 vn += 3;
9438                                 if (vs)
9439                                 {
9440                                         VectorCopy(vs, ts);
9441                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9442                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9443                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9444                                         VectorNormalize(vs);
9445                                         vs += 3;
9446                                         VectorCopy(vt, tt);
9447                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9448                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9449                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9450                                         VectorNormalize(vt);
9451                                         vt += 3;
9452                                 }
9453                         }
9454                 }
9455                 rsurface.batchskeletaltransform3x4 = NULL;
9456                 rsurface.batchskeletalnumtransforms = 0;
9457         }
9458
9459         // q1bsp surfaces rendered in vertex color mode have to have colors
9460         // calculated based on lightstyles
9461         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9462         {
9463                 // generate color arrays for the surfaces in this list
9464                 int c[4];
9465                 int scale;
9466                 int size3;
9467                 const int *offsets;
9468                 const unsigned char *lm;
9469                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9470                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9471                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9472                 numvertices = 0;
9473                 for (i = 0;i < texturenumsurfaces;i++)
9474                 {
9475                         surface = texturesurfacelist[i];
9476                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9477                         surfacenumvertices = surface->num_vertices;
9478                         if (surface->lightmapinfo->samples)
9479                         {
9480                                 for (j = 0;j < surfacenumvertices;j++)
9481                                 {
9482                                         lm = surface->lightmapinfo->samples + offsets[j];
9483                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9484                                         VectorScale(lm, scale, c);
9485                                         if (surface->lightmapinfo->styles[1] != 255)
9486                                         {
9487                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9488                                                 lm += size3;
9489                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9490                                                 VectorMA(c, scale, lm, c);
9491                                                 if (surface->lightmapinfo->styles[2] != 255)
9492                                                 {
9493                                                         lm += size3;
9494                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9495                                                         VectorMA(c, scale, lm, c);
9496                                                         if (surface->lightmapinfo->styles[3] != 255)
9497                                                         {
9498                                                                 lm += size3;
9499                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9500                                                                 VectorMA(c, scale, lm, c);
9501                                                         }
9502                                                 }
9503                                         }
9504                                         c[0] >>= 7;
9505                                         c[1] >>= 7;
9506                                         c[2] >>= 7;
9507                                         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);
9508                                         numvertices++;
9509                                 }
9510                         }
9511                         else
9512                         {
9513                                 for (j = 0;j < surfacenumvertices;j++)
9514                                 {
9515                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9516                                         numvertices++;
9517                                 }
9518                         }
9519                 }
9520         }
9521
9522         // if vertices are deformed (sprite flares and things in maps, possibly
9523         // water waves, bulges and other deformations), modify the copied vertices
9524         // in place
9525         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9526         {
9527                 switch (deform->deform)
9528                 {
9529                 default:
9530                 case Q3DEFORM_PROJECTIONSHADOW:
9531                 case Q3DEFORM_TEXT0:
9532                 case Q3DEFORM_TEXT1:
9533                 case Q3DEFORM_TEXT2:
9534                 case Q3DEFORM_TEXT3:
9535                 case Q3DEFORM_TEXT4:
9536                 case Q3DEFORM_TEXT5:
9537                 case Q3DEFORM_TEXT6:
9538                 case Q3DEFORM_TEXT7:
9539                 case Q3DEFORM_NONE:
9540                         break;
9541                 case Q3DEFORM_AUTOSPRITE:
9542                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9543                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9544                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9545                         VectorNormalize(newforward);
9546                         VectorNormalize(newright);
9547                         VectorNormalize(newup);
9548 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9549 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9550 //                      rsurface.batchvertex3f_bufferoffset = 0;
9551 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9552 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9553 //                      rsurface.batchsvector3f_bufferoffset = 0;
9554 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9555 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9556 //                      rsurface.batchtvector3f_bufferoffset = 0;
9557 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9558 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9559 //                      rsurface.batchnormal3f_bufferoffset = 0;
9560                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9561                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9562                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9563                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9564                                 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);
9565                         // a single autosprite surface can contain multiple sprites...
9566                         for (j = 0;j < batchnumvertices - 3;j += 4)
9567                         {
9568                                 VectorClear(center);
9569                                 for (i = 0;i < 4;i++)
9570                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9571                                 VectorScale(center, 0.25f, center);
9572                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9573                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9574                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9575                                 for (i = 0;i < 4;i++)
9576                                 {
9577                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9578                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9579                                 }
9580                         }
9581                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9582                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9583                         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);
9584                         break;
9585                 case Q3DEFORM_AUTOSPRITE2:
9586                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9587                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9588                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9589                         VectorNormalize(newforward);
9590                         VectorNormalize(newright);
9591                         VectorNormalize(newup);
9592 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9593 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9594 //                      rsurface.batchvertex3f_bufferoffset = 0;
9595                         {
9596                                 const float *v1, *v2;
9597                                 vec3_t start, end;
9598                                 float f, l;
9599                                 struct
9600                                 {
9601                                         float length2;
9602                                         const float *v1;
9603                                         const float *v2;
9604                                 }
9605                                 shortest[2];
9606                                 memset(shortest, 0, sizeof(shortest));
9607                                 // a single autosprite surface can contain multiple sprites...
9608                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9609                                 {
9610                                         VectorClear(center);
9611                                         for (i = 0;i < 4;i++)
9612                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9613                                         VectorScale(center, 0.25f, center);
9614                                         // find the two shortest edges, then use them to define the
9615                                         // axis vectors for rotating around the central axis
9616                                         for (i = 0;i < 6;i++)
9617                                         {
9618                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9619                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9620                                                 l = VectorDistance2(v1, v2);
9621                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9622                                                 if (v1[2] != v2[2])
9623                                                         l += (1.0f / 1024.0f);
9624                                                 if (shortest[0].length2 > l || i == 0)
9625                                                 {
9626                                                         shortest[1] = shortest[0];
9627                                                         shortest[0].length2 = l;
9628                                                         shortest[0].v1 = v1;
9629                                                         shortest[0].v2 = v2;
9630                                                 }
9631                                                 else if (shortest[1].length2 > l || i == 1)
9632                                                 {
9633                                                         shortest[1].length2 = l;
9634                                                         shortest[1].v1 = v1;
9635                                                         shortest[1].v2 = v2;
9636                                                 }
9637                                         }
9638                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9639                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9640                                         // this calculates the right vector from the shortest edge
9641                                         // and the up vector from the edge midpoints
9642                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9643                                         VectorNormalize(right);
9644                                         VectorSubtract(end, start, up);
9645                                         VectorNormalize(up);
9646                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9647                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9648                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9649                                         VectorNegate(forward, forward);
9650                                         VectorReflect(forward, 0, up, forward);
9651                                         VectorNormalize(forward);
9652                                         CrossProduct(up, forward, newright);
9653                                         VectorNormalize(newright);
9654                                         // rotate the quad around the up axis vector, this is made
9655                                         // especially easy by the fact we know the quad is flat,
9656                                         // so we only have to subtract the center position and
9657                                         // measure distance along the right vector, and then
9658                                         // multiply that by the newright vector and add back the
9659                                         // center position
9660                                         // we also need to subtract the old position to undo the
9661                                         // displacement from the center, which we do with a
9662                                         // DotProduct, the subtraction/addition of center is also
9663                                         // optimized into DotProducts here
9664                                         l = DotProduct(right, center);
9665                                         for (i = 0;i < 4;i++)
9666                                         {
9667                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9668                                                 f = DotProduct(right, v1) - l;
9669                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9670                                         }
9671                                 }
9672                         }
9673                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9674                         {
9675 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9676 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9677 //                              rsurface.batchnormal3f_bufferoffset = 0;
9678                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9679                         }
9680                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9681                         {
9682 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9683 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9684 //                              rsurface.batchsvector3f_bufferoffset = 0;
9685 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9686 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9687 //                              rsurface.batchtvector3f_bufferoffset = 0;
9688                                 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);
9689                         }
9690                         break;
9691                 case Q3DEFORM_NORMAL:
9692                         // deform the normals to make reflections wavey
9693                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9694                         rsurface.batchnormal3f_vertexbuffer = NULL;
9695                         rsurface.batchnormal3f_bufferoffset = 0;
9696                         for (j = 0;j < batchnumvertices;j++)
9697                         {
9698                                 float vertex[3];
9699                                 float *normal = rsurface.batchnormal3f + 3*j;
9700                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9701                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9702                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9703                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9704                                 VectorNormalize(normal);
9705                         }
9706                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9707                         {
9708 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9709 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9710 //                              rsurface.batchsvector3f_bufferoffset = 0;
9711 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9712 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9713 //                              rsurface.batchtvector3f_bufferoffset = 0;
9714                                 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);
9715                         }
9716                         break;
9717                 case Q3DEFORM_WAVE:
9718                         // deform vertex array to make wavey water and flags and such
9719                         waveparms[0] = deform->waveparms[0];
9720                         waveparms[1] = deform->waveparms[1];
9721                         waveparms[2] = deform->waveparms[2];
9722                         waveparms[3] = deform->waveparms[3];
9723                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9724                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9725                         // this is how a divisor of vertex influence on deformation
9726                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9727                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9728 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9729 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9730 //                      rsurface.batchvertex3f_bufferoffset = 0;
9731 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9732 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9733 //                      rsurface.batchnormal3f_bufferoffset = 0;
9734                         for (j = 0;j < batchnumvertices;j++)
9735                         {
9736                                 // if the wavefunc depends on time, evaluate it per-vertex
9737                                 if (waveparms[3])
9738                                 {
9739                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9740                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9741                                 }
9742                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9743                         }
9744                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9745                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9746                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9747                         {
9748 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9749 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9750 //                              rsurface.batchsvector3f_bufferoffset = 0;
9751 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9752 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9753 //                              rsurface.batchtvector3f_bufferoffset = 0;
9754                                 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);
9755                         }
9756                         break;
9757                 case Q3DEFORM_BULGE:
9758                         // deform vertex array to make the surface have moving bulges
9759 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9760 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9761 //                      rsurface.batchvertex3f_bufferoffset = 0;
9762 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9763 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9764 //                      rsurface.batchnormal3f_bufferoffset = 0;
9765                         for (j = 0;j < batchnumvertices;j++)
9766                         {
9767                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9768                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9769                         }
9770                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9771                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9772                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9773                         {
9774 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9775 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9776 //                              rsurface.batchsvector3f_bufferoffset = 0;
9777 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9778 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9779 //                              rsurface.batchtvector3f_bufferoffset = 0;
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                         }
9782                         break;
9783                 case Q3DEFORM_MOVE:
9784                         // deform vertex array
9785                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9786                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9787                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9788                         VectorScale(deform->parms, scale, waveparms);
9789 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9790 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9791 //                      rsurface.batchvertex3f_bufferoffset = 0;
9792                         for (j = 0;j < batchnumvertices;j++)
9793                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9794                         break;
9795                 }
9796         }
9797
9798         // generate texcoords based on the chosen texcoord source
9799         switch(rsurface.texture->tcgen.tcgen)
9800         {
9801         default:
9802         case Q3TCGEN_TEXTURE:
9803                 break;
9804         case Q3TCGEN_LIGHTMAP:
9805 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9806 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9807 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9808                 if (rsurface.batchtexcoordlightmap2f)
9809                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9810                 break;
9811         case Q3TCGEN_VECTOR:
9812 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9813 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9814 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9815                 for (j = 0;j < batchnumvertices;j++)
9816                 {
9817                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9818                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9819                 }
9820                 break;
9821         case Q3TCGEN_ENVIRONMENT:
9822                 // make environment reflections using a spheremap
9823                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9824                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9825                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9826                 for (j = 0;j < batchnumvertices;j++)
9827                 {
9828                         // identical to Q3A's method, but executed in worldspace so
9829                         // carried models can be shiny too
9830
9831                         float viewer[3], d, reflected[3], worldreflected[3];
9832
9833                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9834                         // VectorNormalize(viewer);
9835
9836                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9837
9838                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9839                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9840                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9841                         // note: this is proportinal to viewer, so we can normalize later
9842
9843                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9844                         VectorNormalize(worldreflected);
9845
9846                         // note: this sphere map only uses world x and z!
9847                         // so positive and negative y will LOOK THE SAME.
9848                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9849                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9850                 }
9851                 break;
9852         }
9853         // the only tcmod that needs software vertex processing is turbulent, so
9854         // check for it here and apply the changes if needed
9855         // and we only support that as the first one
9856         // (handling a mixture of turbulent and other tcmods would be problematic
9857         //  without punting it entirely to a software path)
9858         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9859         {
9860                 amplitude = rsurface.texture->tcmods[0].parms[1];
9861                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9862 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9863 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9864 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9865                 for (j = 0;j < batchnumvertices;j++)
9866                 {
9867                         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);
9868                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9869                 }
9870         }
9871
9872         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9873         {
9874                 // convert the modified arrays to vertex structs
9875 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9876 //              rsurface.batchvertexmeshbuffer = NULL;
9877                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9878                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9879                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9880                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9881                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9882                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9883                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9884                 {
9885                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9886                         {
9887                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9888                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9889                         }
9890                 }
9891                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9892                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9893                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9894                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9895                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9896                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9897                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9898                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9899                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9900                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9901                 {
9902                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9903                         {
9904                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9905                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9906                         }
9907                 }
9908         }
9909 }
9910
9911 void RSurf_DrawBatch(void)
9912 {
9913         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9914         // through the pipeline, killing it earlier in the pipeline would have
9915         // per-surface overhead rather than per-batch overhead, so it's best to
9916         // reject it here, before it hits glDraw.
9917         if (rsurface.batchnumtriangles == 0)
9918                 return;
9919 #if 0
9920         // batch debugging code
9921         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9922         {
9923                 int i;
9924                 int j;
9925                 int c;
9926                 const int *e;
9927                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9928                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9929                 {
9930                         c = e[i];
9931                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9932                         {
9933                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9934                                 {
9935                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9936                                                 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);
9937                                         break;
9938                                 }
9939                         }
9940                 }
9941         }
9942 #endif
9943         if (rsurface.batchmultidraw)
9944         {
9945                 // issue multiple draws rather than copying index data
9946                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
9947                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
9948                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
9949                 for (i = 0;i < numsurfaces;)
9950                 {
9951                         // combine consecutive surfaces as one draw
9952                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
9953                                 if (surfacelist[j] != surfacelist[k] + 1)
9954                                         break;
9955                         firstvertex = surfacelist[i]->num_firstvertex;
9956                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
9957                         firsttriangle = surfacelist[i]->num_firsttriangle;
9958                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
9959                         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);
9960                         i = j;
9961                 }
9962         }
9963         else
9964         {
9965                 // there is only one consecutive run of index data (may have been combined)
9966                 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);
9967         }
9968 }
9969
9970 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9971 {
9972         // pick the closest matching water plane
9973         int planeindex, vertexindex, bestplaneindex = -1;
9974         float d, bestd;
9975         vec3_t vert;
9976         const float *v;
9977         r_waterstate_waterplane_t *p;
9978         qboolean prepared = false;
9979         bestd = 0;
9980         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9981         {
9982                 if(p->camera_entity != rsurface.texture->camera_entity)
9983                         continue;
9984                 d = 0;
9985                 if(!prepared)
9986                 {
9987                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
9988                         prepared = true;
9989                         if(rsurface.batchnumvertices == 0)
9990                                 break;
9991                 }
9992                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9993                 {
9994                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9995                         d += fabs(PlaneDiff(vert, &p->plane));
9996                 }
9997                 if (bestd > d || bestplaneindex < 0)
9998                 {
9999                         bestd = d;
10000                         bestplaneindex = planeindex;
10001                 }
10002         }
10003         return bestplaneindex;
10004         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10005         // this situation though, as it might be better to render single larger
10006         // batches with useless stuff (backface culled for example) than to
10007         // render multiple smaller batches
10008 }
10009
10010 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10011 {
10012         int i;
10013         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10014         rsurface.passcolor4f_vertexbuffer = 0;
10015         rsurface.passcolor4f_bufferoffset = 0;
10016         for (i = 0;i < rsurface.batchnumvertices;i++)
10017                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10018 }
10019
10020 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10021 {
10022         int i;
10023         float f;
10024         const float *v;
10025         const float *c;
10026         float *c2;
10027         if (rsurface.passcolor4f)
10028         {
10029                 // generate color arrays
10030                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10031                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10032                 rsurface.passcolor4f_vertexbuffer = 0;
10033                 rsurface.passcolor4f_bufferoffset = 0;
10034                 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)
10035                 {
10036                         f = RSurf_FogVertex(v);
10037                         c2[0] = c[0] * f;
10038                         c2[1] = c[1] * f;
10039                         c2[2] = c[2] * f;
10040                         c2[3] = c[3];
10041                 }
10042         }
10043         else
10044         {
10045                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10046                 rsurface.passcolor4f_vertexbuffer = 0;
10047                 rsurface.passcolor4f_bufferoffset = 0;
10048                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10049                 {
10050                         f = RSurf_FogVertex(v);
10051                         c2[0] = f;
10052                         c2[1] = f;
10053                         c2[2] = f;
10054                         c2[3] = 1;
10055                 }
10056         }
10057 }
10058
10059 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10060 {
10061         int i;
10062         float f;
10063         const float *v;
10064         const float *c;
10065         float *c2;
10066         if (!rsurface.passcolor4f)
10067                 return;
10068         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10069         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10070         rsurface.passcolor4f_vertexbuffer = 0;
10071         rsurface.passcolor4f_bufferoffset = 0;
10072         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)
10073         {
10074                 f = RSurf_FogVertex(v);
10075                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10076                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10077                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10078                 c2[3] = c[3];
10079         }
10080 }
10081
10082 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10083 {
10084         int i;
10085         const float *c;
10086         float *c2;
10087         if (!rsurface.passcolor4f)
10088                 return;
10089         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10090         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10091         rsurface.passcolor4f_vertexbuffer = 0;
10092         rsurface.passcolor4f_bufferoffset = 0;
10093         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10094         {
10095                 c2[0] = c[0] * r;
10096                 c2[1] = c[1] * g;
10097                 c2[2] = c[2] * b;
10098                 c2[3] = c[3] * a;
10099         }
10100 }
10101
10102 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10103 {
10104         int i;
10105         const float *c;
10106         float *c2;
10107         if (!rsurface.passcolor4f)
10108                 return;
10109         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10110         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10111         rsurface.passcolor4f_vertexbuffer = 0;
10112         rsurface.passcolor4f_bufferoffset = 0;
10113         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10114         {
10115                 c2[0] = c[0] + r_refdef.scene.ambient;
10116                 c2[1] = c[1] + r_refdef.scene.ambient;
10117                 c2[2] = c[2] + r_refdef.scene.ambient;
10118                 c2[3] = c[3];
10119         }
10120 }
10121
10122 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10123 {
10124         // TODO: optimize
10125         rsurface.passcolor4f = NULL;
10126         rsurface.passcolor4f_vertexbuffer = 0;
10127         rsurface.passcolor4f_bufferoffset = 0;
10128         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10129         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10130         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10131         GL_Color(r, g, b, a);
10132         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10133         RSurf_DrawBatch();
10134 }
10135
10136 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10137 {
10138         // TODO: optimize applyfog && applycolor case
10139         // just apply fog if necessary, and tint the fog color array if necessary
10140         rsurface.passcolor4f = NULL;
10141         rsurface.passcolor4f_vertexbuffer = 0;
10142         rsurface.passcolor4f_bufferoffset = 0;
10143         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10144         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10145         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10146         GL_Color(r, g, b, a);
10147         RSurf_DrawBatch();
10148 }
10149
10150 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10151 {
10152         // TODO: optimize
10153         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10154         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10155         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10156         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10157         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10158         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10159         GL_Color(r, g, b, a);
10160         RSurf_DrawBatch();
10161 }
10162
10163 static void RSurf_DrawBatch_GL11_ClampColor(void)
10164 {
10165         int i;
10166         const float *c1;
10167         float *c2;
10168         if (!rsurface.passcolor4f)
10169                 return;
10170         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10171         {
10172                 c2[0] = bound(0.0f, c1[0], 1.0f);
10173                 c2[1] = bound(0.0f, c1[1], 1.0f);
10174                 c2[2] = bound(0.0f, c1[2], 1.0f);
10175                 c2[3] = bound(0.0f, c1[3], 1.0f);
10176         }
10177 }
10178
10179 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10180 {
10181         int i;
10182         float f;
10183         const float *v;
10184         const float *n;
10185         float *c;
10186         //vec3_t eyedir;
10187
10188         // fake shading
10189         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10190         rsurface.passcolor4f_vertexbuffer = 0;
10191         rsurface.passcolor4f_bufferoffset = 0;
10192         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)
10193         {
10194                 f = -DotProduct(r_refdef.view.forward, n);
10195                 f = max(0, f);
10196                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10197                 f *= r_refdef.lightmapintensity;
10198                 Vector4Set(c, f, f, f, 1);
10199         }
10200 }
10201
10202 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10203 {
10204         RSurf_DrawBatch_GL11_ApplyFakeLight();
10205         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10206         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10207         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10208         GL_Color(r, g, b, a);
10209         RSurf_DrawBatch();
10210 }
10211
10212 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10213 {
10214         int i;
10215         float f;
10216         float alpha;
10217         const float *v;
10218         const float *n;
10219         float *c;
10220         vec3_t ambientcolor;
10221         vec3_t diffusecolor;
10222         vec3_t lightdir;
10223         // TODO: optimize
10224         // model lighting
10225         VectorCopy(rsurface.modellight_lightdir, lightdir);
10226         f = 0.5f * r_refdef.lightmapintensity;
10227         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10228         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10229         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10230         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10231         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10232         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10233         alpha = *a;
10234         if (VectorLength2(diffusecolor) > 0)
10235         {
10236                 // q3-style directional shading
10237                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10238                 rsurface.passcolor4f_vertexbuffer = 0;
10239                 rsurface.passcolor4f_bufferoffset = 0;
10240                 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)
10241                 {
10242                         if ((f = DotProduct(n, lightdir)) > 0)
10243                                 VectorMA(ambientcolor, f, diffusecolor, c);
10244                         else
10245                                 VectorCopy(ambientcolor, c);
10246                         c[3] = alpha;
10247                 }
10248                 *r = 1;
10249                 *g = 1;
10250                 *b = 1;
10251                 *a = 1;
10252                 *applycolor = false;
10253         }
10254         else
10255         {
10256                 *r = ambientcolor[0];
10257                 *g = ambientcolor[1];
10258                 *b = ambientcolor[2];
10259                 rsurface.passcolor4f = NULL;
10260                 rsurface.passcolor4f_vertexbuffer = 0;
10261                 rsurface.passcolor4f_bufferoffset = 0;
10262         }
10263 }
10264
10265 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10266 {
10267         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10268         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10269         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10270         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10271         GL_Color(r, g, b, a);
10272         RSurf_DrawBatch();
10273 }
10274
10275 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10276 {
10277         int i;
10278         float f;
10279         const float *v;
10280         float *c;
10281
10282         // fake shading
10283         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10284         rsurface.passcolor4f_vertexbuffer = 0;
10285         rsurface.passcolor4f_bufferoffset = 0;
10286
10287         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10288         {
10289                 f = 1 - RSurf_FogVertex(v);
10290                 c[0] = r;
10291                 c[1] = g;
10292                 c[2] = b;
10293                 c[3] = f * a;
10294         }
10295 }
10296
10297 void RSurf_SetupDepthAndCulling(void)
10298 {
10299         // submodels are biased to avoid z-fighting with world surfaces that they
10300         // may be exactly overlapping (avoids z-fighting artifacts on certain
10301         // doors and things in Quake maps)
10302         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10303         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10304         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10305         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10306 }
10307
10308 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10309 {
10310         // transparent sky would be ridiculous
10311         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10312                 return;
10313         R_SetupShader_Generic_NoTexture(false, false);
10314         skyrenderlater = true;
10315         RSurf_SetupDepthAndCulling();
10316         GL_DepthMask(true);
10317         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10318         // skymasking on them, and Quake3 never did sky masking (unlike
10319         // software Quake and software Quake2), so disable the sky masking
10320         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10321         // and skymasking also looks very bad when noclipping outside the
10322         // level, so don't use it then either.
10323         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10324         {
10325                 R_Mesh_ResetTextureState();
10326                 if (skyrendermasked)
10327                 {
10328                         R_SetupShader_DepthOrShadow(false, false, false);
10329                         // depth-only (masking)
10330                         GL_ColorMask(0,0,0,0);
10331                         // just to make sure that braindead drivers don't draw
10332                         // anything despite that colormask...
10333                         GL_BlendFunc(GL_ZERO, GL_ONE);
10334                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10335                         if (rsurface.batchvertex3fbuffer)
10336                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10337                         else
10338                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10339                 }
10340                 else
10341                 {
10342                         R_SetupShader_Generic_NoTexture(false, false);
10343                         // fog sky
10344                         GL_BlendFunc(GL_ONE, GL_ZERO);
10345                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10346                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10347                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10348                 }
10349                 RSurf_DrawBatch();
10350                 if (skyrendermasked)
10351                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10352         }
10353         R_Mesh_ResetTextureState();
10354         GL_Color(1, 1, 1, 1);
10355 }
10356
10357 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10358 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10359 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10360 {
10361         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10362                 return;
10363         if (prepass)
10364         {
10365                 // render screenspace normalmap to texture
10366                 GL_DepthMask(true);
10367                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10368                 RSurf_DrawBatch();
10369                 return;
10370         }
10371
10372         // bind lightmap texture
10373
10374         // water/refraction/reflection/camera surfaces have to be handled specially
10375         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10376         {
10377                 int start, end, startplaneindex;
10378                 for (start = 0;start < texturenumsurfaces;start = end)
10379                 {
10380                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10381                         if(startplaneindex < 0)
10382                         {
10383                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10384                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10385                                 end = start + 1;
10386                                 continue;
10387                         }
10388                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10389                                 ;
10390                         // now that we have a batch using the same planeindex, render it
10391                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10392                         {
10393                                 // render water or distortion background
10394                                 GL_DepthMask(true);
10395                                 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);
10396                                 RSurf_DrawBatch();
10397                                 // blend surface on top
10398                                 GL_DepthMask(false);
10399                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10400                                 RSurf_DrawBatch();
10401                         }
10402                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10403                         {
10404                                 // render surface with reflection texture as input
10405                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10406                                 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);
10407                                 RSurf_DrawBatch();
10408                         }
10409                 }
10410                 return;
10411         }
10412
10413         // render surface batch normally
10414         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10415         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);
10416         RSurf_DrawBatch();
10417 }
10418
10419 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10420 {
10421         // OpenGL 1.3 path - anything not completely ancient
10422         qboolean applycolor;
10423         qboolean applyfog;
10424         int layerindex;
10425         const texturelayer_t *layer;
10426         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);
10427         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10428
10429         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10430         {
10431                 vec4_t layercolor;
10432                 int layertexrgbscale;
10433                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10434                 {
10435                         if (layerindex == 0)
10436                                 GL_AlphaTest(true);
10437                         else
10438                         {
10439                                 GL_AlphaTest(false);
10440                                 GL_DepthFunc(GL_EQUAL);
10441                         }
10442                 }
10443                 GL_DepthMask(layer->depthmask && writedepth);
10444                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10445                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10446                 {
10447                         layertexrgbscale = 4;
10448                         VectorScale(layer->color, 0.25f, layercolor);
10449                 }
10450                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10451                 {
10452                         layertexrgbscale = 2;
10453                         VectorScale(layer->color, 0.5f, layercolor);
10454                 }
10455                 else
10456                 {
10457                         layertexrgbscale = 1;
10458                         VectorScale(layer->color, 1.0f, layercolor);
10459                 }
10460                 layercolor[3] = layer->color[3];
10461                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10462                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10463                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10464                 switch (layer->type)
10465                 {
10466                 case TEXTURELAYERTYPE_LITTEXTURE:
10467                         // single-pass lightmapped texture with 2x rgbscale
10468                         R_Mesh_TexBind(0, r_texture_white);
10469                         R_Mesh_TexMatrix(0, NULL);
10470                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10471                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10472                         R_Mesh_TexBind(1, layer->texture);
10473                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10474                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10475                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10476                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10477                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10478                         else if (FAKELIGHT_ENABLED)
10479                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10480                         else if (rsurface.uselightmaptexture)
10481                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10482                         else
10483                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10484                         break;
10485                 case TEXTURELAYERTYPE_TEXTURE:
10486                         // singletexture unlit texture with transparency support
10487                         R_Mesh_TexBind(0, layer->texture);
10488                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10489                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10490                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10491                         R_Mesh_TexBind(1, 0);
10492                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10493                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10494                         break;
10495                 case TEXTURELAYERTYPE_FOG:
10496                         // singletexture fogging
10497                         if (layer->texture)
10498                         {
10499                                 R_Mesh_TexBind(0, layer->texture);
10500                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10501                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10502                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10503                         }
10504                         else
10505                         {
10506                                 R_Mesh_TexBind(0, 0);
10507                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10508                         }
10509                         R_Mesh_TexBind(1, 0);
10510                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10511                         // generate a color array for the fog pass
10512                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10513                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10514                         RSurf_DrawBatch();
10515                         break;
10516                 default:
10517                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10518                 }
10519         }
10520         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10521         {
10522                 GL_DepthFunc(GL_LEQUAL);
10523                 GL_AlphaTest(false);
10524         }
10525 }
10526
10527 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10528 {
10529         // OpenGL 1.1 - crusty old voodoo path
10530         qboolean applyfog;
10531         int layerindex;
10532         const texturelayer_t *layer;
10533         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);
10534         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10535
10536         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10537         {
10538                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10539                 {
10540                         if (layerindex == 0)
10541                                 GL_AlphaTest(true);
10542                         else
10543                         {
10544                                 GL_AlphaTest(false);
10545                                 GL_DepthFunc(GL_EQUAL);
10546                         }
10547                 }
10548                 GL_DepthMask(layer->depthmask && writedepth);
10549                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10550                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10551                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10552                 switch (layer->type)
10553                 {
10554                 case TEXTURELAYERTYPE_LITTEXTURE:
10555                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10556                         {
10557                                 // two-pass lit texture with 2x rgbscale
10558                                 // first the lightmap pass
10559                                 R_Mesh_TexBind(0, r_texture_white);
10560                                 R_Mesh_TexMatrix(0, NULL);
10561                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10562                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10563                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10564                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10565                                 else if (FAKELIGHT_ENABLED)
10566                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10567                                 else if (rsurface.uselightmaptexture)
10568                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10569                                 else
10570                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10571                                 // then apply the texture to it
10572                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10573                                 R_Mesh_TexBind(0, layer->texture);
10574                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10575                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10576                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10577                                 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);
10578                         }
10579                         else
10580                         {
10581                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10582                                 R_Mesh_TexBind(0, layer->texture);
10583                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10584                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10585                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10586                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10587                                         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);
10588                                 else if (FAKELIGHT_ENABLED)
10589                                         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);
10590                                 else
10591                                         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);
10592                         }
10593                         break;
10594                 case TEXTURELAYERTYPE_TEXTURE:
10595                         // singletexture unlit texture with transparency support
10596                         R_Mesh_TexBind(0, layer->texture);
10597                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10598                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10599                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10600                         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);
10601                         break;
10602                 case TEXTURELAYERTYPE_FOG:
10603                         // singletexture fogging
10604                         if (layer->texture)
10605                         {
10606                                 R_Mesh_TexBind(0, layer->texture);
10607                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10608                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10609                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10610                         }
10611                         else
10612                         {
10613                                 R_Mesh_TexBind(0, 0);
10614                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10615                         }
10616                         // generate a color array for the fog pass
10617                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10618                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10619                         RSurf_DrawBatch();
10620                         break;
10621                 default:
10622                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10623                 }
10624         }
10625         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10626         {
10627                 GL_DepthFunc(GL_LEQUAL);
10628                 GL_AlphaTest(false);
10629         }
10630 }
10631
10632 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10633 {
10634         int vi;
10635         int j;
10636         r_vertexgeneric_t *batchvertex;
10637         float c[4];
10638
10639 //      R_Mesh_ResetTextureState();
10640         R_SetupShader_Generic_NoTexture(false, false);
10641
10642         if(rsurface.texture && rsurface.texture->currentskinframe)
10643         {
10644                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10645                 c[3] *= rsurface.texture->currentalpha;
10646         }
10647         else
10648         {
10649                 c[0] = 1;
10650                 c[1] = 0;
10651                 c[2] = 1;
10652                 c[3] = 1;
10653         }
10654
10655         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10656         {
10657                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10658                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10659                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10660         }
10661
10662         // brighten it up (as texture value 127 means "unlit")
10663         c[0] *= 2 * r_refdef.view.colorscale;
10664         c[1] *= 2 * r_refdef.view.colorscale;
10665         c[2] *= 2 * r_refdef.view.colorscale;
10666
10667         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10668                 c[3] *= r_wateralpha.value;
10669
10670         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10671         {
10672                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10673                 GL_DepthMask(false);
10674         }
10675         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10676         {
10677                 GL_BlendFunc(GL_ONE, GL_ONE);
10678                 GL_DepthMask(false);
10679         }
10680         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10681         {
10682                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10683                 GL_DepthMask(false);
10684         }
10685         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10686         {
10687                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10688                 GL_DepthMask(false);
10689         }
10690         else
10691         {
10692                 GL_BlendFunc(GL_ONE, GL_ZERO);
10693                 GL_DepthMask(writedepth);
10694         }
10695
10696         if (r_showsurfaces.integer == 3)
10697         {
10698                 rsurface.passcolor4f = NULL;
10699
10700                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10701                 {
10702                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10703
10704                         rsurface.passcolor4f = NULL;
10705                         rsurface.passcolor4f_vertexbuffer = 0;
10706                         rsurface.passcolor4f_bufferoffset = 0;
10707                 }
10708                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10709                 {
10710                         qboolean applycolor = true;
10711                         float one = 1.0;
10712
10713                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10714
10715                         r_refdef.lightmapintensity = 1;
10716                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10717                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10718                 }
10719                 else if (FAKELIGHT_ENABLED)
10720                 {
10721                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10722
10723                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10724                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10725                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10726                 }
10727                 else
10728                 {
10729                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10730
10731                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10732                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10733                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10734                 }
10735
10736                 if(!rsurface.passcolor4f)
10737                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10738
10739                 RSurf_DrawBatch_GL11_ApplyAmbient();
10740                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10741                 if(r_refdef.fogenabled)
10742                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10743                 RSurf_DrawBatch_GL11_ClampColor();
10744
10745                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10746                 R_SetupShader_Generic_NoTexture(false, false);
10747                 RSurf_DrawBatch();
10748         }
10749         else if (!r_refdef.view.showdebug)
10750         {
10751                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10752                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10753                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10754                 {
10755                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10756                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10757                 }
10758                 R_Mesh_PrepareVertices_Generic_Unlock();
10759                 RSurf_DrawBatch();
10760         }
10761         else if (r_showsurfaces.integer == 4)
10762         {
10763                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10764                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10765                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10766                 {
10767                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10768                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10769                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10770                 }
10771                 R_Mesh_PrepareVertices_Generic_Unlock();
10772                 RSurf_DrawBatch();
10773         }
10774         else if (r_showsurfaces.integer == 2)
10775         {
10776                 const int *e;
10777                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10778                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10779                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10780                 {
10781                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10782                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10783                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10784                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10785                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10786                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10787                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10788                 }
10789                 R_Mesh_PrepareVertices_Generic_Unlock();
10790                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10791         }
10792         else
10793         {
10794                 int texturesurfaceindex;
10795                 int k;
10796                 const msurface_t *surface;
10797                 float surfacecolor4f[4];
10798                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10799                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10800                 vi = 0;
10801                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10802                 {
10803                         surface = texturesurfacelist[texturesurfaceindex];
10804                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10805                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10806                         for (j = 0;j < surface->num_vertices;j++)
10807                         {
10808                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10809                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10810                                 vi++;
10811                         }
10812                 }
10813                 R_Mesh_PrepareVertices_Generic_Unlock();
10814                 RSurf_DrawBatch();
10815         }
10816 }
10817
10818 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10819 {
10820         CHECKGLERROR
10821         RSurf_SetupDepthAndCulling();
10822         if (r_showsurfaces.integer)
10823         {
10824                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10825                 return;
10826         }
10827         switch (vid.renderpath)
10828         {
10829         case RENDERPATH_GL20:
10830         case RENDERPATH_D3D9:
10831         case RENDERPATH_D3D10:
10832         case RENDERPATH_D3D11:
10833         case RENDERPATH_SOFT:
10834         case RENDERPATH_GLES2:
10835                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10836                 break;
10837         case RENDERPATH_GL13:
10838         case RENDERPATH_GLES1:
10839                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10840                 break;
10841         case RENDERPATH_GL11:
10842                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10843                 break;
10844         }
10845         CHECKGLERROR
10846 }
10847
10848 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10849 {
10850         CHECKGLERROR
10851         RSurf_SetupDepthAndCulling();
10852         if (r_showsurfaces.integer)
10853         {
10854                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10855                 return;
10856         }
10857         switch (vid.renderpath)
10858         {
10859         case RENDERPATH_GL20:
10860         case RENDERPATH_D3D9:
10861         case RENDERPATH_D3D10:
10862         case RENDERPATH_D3D11:
10863         case RENDERPATH_SOFT:
10864         case RENDERPATH_GLES2:
10865                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10866                 break;
10867         case RENDERPATH_GL13:
10868         case RENDERPATH_GLES1:
10869                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10870                 break;
10871         case RENDERPATH_GL11:
10872                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10873                 break;
10874         }
10875         CHECKGLERROR
10876 }
10877
10878 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10879 {
10880         int i, j;
10881         int texturenumsurfaces, endsurface;
10882         texture_t *texture;
10883         const msurface_t *surface;
10884         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10885
10886         // if the model is static it doesn't matter what value we give for
10887         // wantnormals and wanttangents, so this logic uses only rules applicable
10888         // to a model, knowing that they are meaningless otherwise
10889         if (ent == r_refdef.scene.worldentity)
10890                 RSurf_ActiveWorldEntity();
10891         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10892                 RSurf_ActiveModelEntity(ent, false, false, false);
10893         else
10894         {
10895                 switch (vid.renderpath)
10896                 {
10897                 case RENDERPATH_GL20:
10898                 case RENDERPATH_D3D9:
10899                 case RENDERPATH_D3D10:
10900                 case RENDERPATH_D3D11:
10901                 case RENDERPATH_SOFT:
10902                 case RENDERPATH_GLES2:
10903                         RSurf_ActiveModelEntity(ent, true, true, false);
10904                         break;
10905                 case RENDERPATH_GL11:
10906                 case RENDERPATH_GL13:
10907                 case RENDERPATH_GLES1:
10908                         RSurf_ActiveModelEntity(ent, true, false, false);
10909                         break;
10910                 }
10911         }
10912
10913         if (r_transparentdepthmasking.integer)
10914         {
10915                 qboolean setup = false;
10916                 for (i = 0;i < numsurfaces;i = j)
10917                 {
10918                         j = i + 1;
10919                         surface = rsurface.modelsurfaces + surfacelist[i];
10920                         texture = surface->texture;
10921                         rsurface.texture = R_GetCurrentTexture(texture);
10922                         rsurface.lightmaptexture = NULL;
10923                         rsurface.deluxemaptexture = NULL;
10924                         rsurface.uselightmaptexture = false;
10925                         // scan ahead until we find a different texture
10926                         endsurface = min(i + 1024, numsurfaces);
10927                         texturenumsurfaces = 0;
10928                         texturesurfacelist[texturenumsurfaces++] = surface;
10929                         for (;j < endsurface;j++)
10930                         {
10931                                 surface = rsurface.modelsurfaces + surfacelist[j];
10932                                 if (texture != surface->texture)
10933                                         break;
10934                                 texturesurfacelist[texturenumsurfaces++] = surface;
10935                         }
10936                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10937                                 continue;
10938                         // render the range of surfaces as depth
10939                         if (!setup)
10940                         {
10941                                 setup = true;
10942                                 GL_ColorMask(0,0,0,0);
10943                                 GL_Color(1,1,1,1);
10944                                 GL_DepthTest(true);
10945                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10946                                 GL_DepthMask(true);
10947 //                              R_Mesh_ResetTextureState();
10948                         }
10949                         RSurf_SetupDepthAndCulling();
10950                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10951                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
10952                         if (rsurface.batchvertex3fbuffer)
10953                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10954                         else
10955                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10956                         RSurf_DrawBatch();
10957                 }
10958                 if (setup)
10959                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10960         }
10961
10962         for (i = 0;i < numsurfaces;i = j)
10963         {
10964                 j = i + 1;
10965                 surface = rsurface.modelsurfaces + surfacelist[i];
10966                 texture = surface->texture;
10967                 rsurface.texture = R_GetCurrentTexture(texture);
10968                 // scan ahead until we find a different texture
10969                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10970                 texturenumsurfaces = 0;
10971                 texturesurfacelist[texturenumsurfaces++] = surface;
10972                 if(FAKELIGHT_ENABLED)
10973                 {
10974                         rsurface.lightmaptexture = NULL;
10975                         rsurface.deluxemaptexture = NULL;
10976                         rsurface.uselightmaptexture = false;
10977                         for (;j < endsurface;j++)
10978                         {
10979                                 surface = rsurface.modelsurfaces + surfacelist[j];
10980                                 if (texture != surface->texture)
10981                                         break;
10982                                 texturesurfacelist[texturenumsurfaces++] = surface;
10983                         }
10984                 }
10985                 else
10986                 {
10987                         rsurface.lightmaptexture = surface->lightmaptexture;
10988                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10989                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10990                         for (;j < endsurface;j++)
10991                         {
10992                                 surface = rsurface.modelsurfaces + surfacelist[j];
10993                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10994                                         break;
10995                                 texturesurfacelist[texturenumsurfaces++] = surface;
10996                         }
10997                 }
10998                 // render the range of surfaces
10999                 if (ent == r_refdef.scene.worldentity)
11000                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11001                 else
11002                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11003         }
11004         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11005 }
11006
11007 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11008 {
11009         // transparent surfaces get pushed off into the transparent queue
11010         int surfacelistindex;
11011         const msurface_t *surface;
11012         vec3_t tempcenter, center;
11013         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11014         {
11015                 surface = texturesurfacelist[surfacelistindex];
11016                 if (r_transparent_sortsurfacesbynearest.integer)
11017                 {
11018                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11019                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11020                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11021                 }
11022                 else
11023                 {
11024                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11025                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11026                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11027                 }
11028                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11029                 if (rsurface.entity->transparent_offset) // transparent offset
11030                 {
11031                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11032                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11033                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11034                 }
11035                 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);
11036         }
11037 }
11038
11039 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11040 {
11041         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11042                 return;
11043         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11044                 return;
11045         RSurf_SetupDepthAndCulling();
11046         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11047         if (rsurface.batchvertex3fbuffer)
11048                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
11049         else
11050                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
11051         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11052         RSurf_DrawBatch();
11053 }
11054
11055 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11056 {
11057         CHECKGLERROR
11058         if (depthonly)
11059                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11060         else if (prepass)
11061         {
11062                 if (!rsurface.texture->currentnumlayers)
11063                         return;
11064                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11065                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11066                 else
11067                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11068         }
11069         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11070                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11071         else if (!rsurface.texture->currentnumlayers)
11072                 return;
11073         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11074         {
11075                 // in the deferred case, transparent surfaces were queued during prepass
11076                 if (!r_shadow_usingdeferredprepass)
11077                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11078         }
11079         else
11080         {
11081                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11082                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11083         }
11084         CHECKGLERROR
11085 }
11086
11087 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11088 {
11089         int i, j;
11090         texture_t *texture;
11091         R_FrameData_SetMark();
11092         // break the surface list down into batches by texture and use of lightmapping
11093         for (i = 0;i < numsurfaces;i = j)
11094         {
11095                 j = i + 1;
11096                 // texture is the base texture pointer, rsurface.texture is the
11097                 // current frame/skin the texture is directing us to use (for example
11098                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11099                 // use skin 1 instead)
11100                 texture = surfacelist[i]->texture;
11101                 rsurface.texture = R_GetCurrentTexture(texture);
11102                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11103                 {
11104                         // if this texture is not the kind we want, skip ahead to the next one
11105                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11106                                 ;
11107                         continue;
11108                 }
11109                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11110                 {
11111                         rsurface.lightmaptexture = NULL;
11112                         rsurface.deluxemaptexture = NULL;
11113                         rsurface.uselightmaptexture = false;
11114                         // simply scan ahead until we find a different texture or lightmap state
11115                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11116                                 ;
11117                 }
11118                 else
11119                 {
11120                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11121                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11122                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11123                         // simply scan ahead until we find a different texture or lightmap state
11124                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11125                                 ;
11126                 }
11127                 // render the range of surfaces
11128                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11129         }
11130         R_FrameData_ReturnToMark();
11131 }
11132
11133 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11134 {
11135         CHECKGLERROR
11136         if (depthonly)
11137                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11138         else if (prepass)
11139         {
11140                 if (!rsurface.texture->currentnumlayers)
11141                         return;
11142                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11143                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11144                 else
11145                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11146         }
11147         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11148                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11149         else if (!rsurface.texture->currentnumlayers)
11150                 return;
11151         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11152         {
11153                 // in the deferred case, transparent surfaces were queued during prepass
11154                 if (!r_shadow_usingdeferredprepass)
11155                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11156         }
11157         else
11158         {
11159                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11160                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11161         }
11162         CHECKGLERROR
11163 }
11164
11165 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11166 {
11167         int i, j;
11168         texture_t *texture;
11169         R_FrameData_SetMark();
11170         // break the surface list down into batches by texture and use of lightmapping
11171         for (i = 0;i < numsurfaces;i = j)
11172         {
11173                 j = i + 1;
11174                 // texture is the base texture pointer, rsurface.texture is the
11175                 // current frame/skin the texture is directing us to use (for example
11176                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11177                 // use skin 1 instead)
11178                 texture = surfacelist[i]->texture;
11179                 rsurface.texture = R_GetCurrentTexture(texture);
11180                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11181                 {
11182                         // if this texture is not the kind we want, skip ahead to the next one
11183                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11184                                 ;
11185                         continue;
11186                 }
11187                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11188                 {
11189                         rsurface.lightmaptexture = NULL;
11190                         rsurface.deluxemaptexture = NULL;
11191                         rsurface.uselightmaptexture = false;
11192                         // simply scan ahead until we find a different texture or lightmap state
11193                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11194                                 ;
11195                 }
11196                 else
11197                 {
11198                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11199                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11200                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11201                         // simply scan ahead until we find a different texture or lightmap state
11202                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11203                                 ;
11204                 }
11205                 // render the range of surfaces
11206                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11207         }
11208         R_FrameData_ReturnToMark();
11209 }
11210
11211 float locboxvertex3f[6*4*3] =
11212 {
11213         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11214         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11215         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11216         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11217         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11218         1,0,0, 0,0,0, 0,1,0, 1,1,0
11219 };
11220
11221 unsigned short locboxelements[6*2*3] =
11222 {
11223          0, 1, 2, 0, 2, 3,
11224          4, 5, 6, 4, 6, 7,
11225          8, 9,10, 8,10,11,
11226         12,13,14, 12,14,15,
11227         16,17,18, 16,18,19,
11228         20,21,22, 20,22,23
11229 };
11230
11231 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11232 {
11233         int i, j;
11234         cl_locnode_t *loc = (cl_locnode_t *)ent;
11235         vec3_t mins, size;
11236         float vertex3f[6*4*3];
11237         CHECKGLERROR
11238         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11239         GL_DepthMask(false);
11240         GL_DepthRange(0, 1);
11241         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11242         GL_DepthTest(true);
11243         GL_CullFace(GL_NONE);
11244         R_EntityMatrix(&identitymatrix);
11245
11246 //      R_Mesh_ResetTextureState();
11247
11248         i = surfacelist[0];
11249         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11250                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11251                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11252                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11253
11254         if (VectorCompare(loc->mins, loc->maxs))
11255         {
11256                 VectorSet(size, 2, 2, 2);
11257                 VectorMA(loc->mins, -0.5f, size, mins);
11258         }
11259         else
11260         {
11261                 VectorCopy(loc->mins, mins);
11262                 VectorSubtract(loc->maxs, loc->mins, size);
11263         }
11264
11265         for (i = 0;i < 6*4*3;)
11266                 for (j = 0;j < 3;j++, i++)
11267                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11268
11269         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11270         R_SetupShader_Generic_NoTexture(false, false);
11271         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11272 }
11273
11274 void R_DrawLocs(void)
11275 {
11276         int index;
11277         cl_locnode_t *loc, *nearestloc;
11278         vec3_t center;
11279         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11280         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11281         {
11282                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11283                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11284         }
11285 }
11286
11287 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11288 {
11289         if (decalsystem->decals)
11290                 Mem_Free(decalsystem->decals);
11291         memset(decalsystem, 0, sizeof(*decalsystem));
11292 }
11293
11294 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)
11295 {
11296         tridecal_t *decal;
11297         tridecal_t *decals;
11298         int i;
11299
11300         // expand or initialize the system
11301         if (decalsystem->maxdecals <= decalsystem->numdecals)
11302         {
11303                 decalsystem_t old = *decalsystem;
11304                 qboolean useshortelements;
11305                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11306                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11307                 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)));
11308                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11309                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11310                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11311                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11312                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11313                 if (decalsystem->numdecals)
11314                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11315                 if (old.decals)
11316                         Mem_Free(old.decals);
11317                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11318                         decalsystem->element3i[i] = i;
11319                 if (useshortelements)
11320                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11321                                 decalsystem->element3s[i] = i;
11322         }
11323
11324         // grab a decal and search for another free slot for the next one
11325         decals = decalsystem->decals;
11326         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11327         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11328                 ;
11329         decalsystem->freedecal = i;
11330         if (decalsystem->numdecals <= i)
11331                 decalsystem->numdecals = i + 1;
11332
11333         // initialize the decal
11334         decal->lived = 0;
11335         decal->triangleindex = triangleindex;
11336         decal->surfaceindex = surfaceindex;
11337         decal->decalsequence = decalsequence;
11338         decal->color4f[0][0] = c0[0];
11339         decal->color4f[0][1] = c0[1];
11340         decal->color4f[0][2] = c0[2];
11341         decal->color4f[0][3] = 1;
11342         decal->color4f[1][0] = c1[0];
11343         decal->color4f[1][1] = c1[1];
11344         decal->color4f[1][2] = c1[2];
11345         decal->color4f[1][3] = 1;
11346         decal->color4f[2][0] = c2[0];
11347         decal->color4f[2][1] = c2[1];
11348         decal->color4f[2][2] = c2[2];
11349         decal->color4f[2][3] = 1;
11350         decal->vertex3f[0][0] = v0[0];
11351         decal->vertex3f[0][1] = v0[1];
11352         decal->vertex3f[0][2] = v0[2];
11353         decal->vertex3f[1][0] = v1[0];
11354         decal->vertex3f[1][1] = v1[1];
11355         decal->vertex3f[1][2] = v1[2];
11356         decal->vertex3f[2][0] = v2[0];
11357         decal->vertex3f[2][1] = v2[1];
11358         decal->vertex3f[2][2] = v2[2];
11359         decal->texcoord2f[0][0] = t0[0];
11360         decal->texcoord2f[0][1] = t0[1];
11361         decal->texcoord2f[1][0] = t1[0];
11362         decal->texcoord2f[1][1] = t1[1];
11363         decal->texcoord2f[2][0] = t2[0];
11364         decal->texcoord2f[2][1] = t2[1];
11365         TriangleNormal(v0, v1, v2, decal->plane);
11366         VectorNormalize(decal->plane);
11367         decal->plane[3] = DotProduct(v0, decal->plane);
11368 }
11369
11370 extern cvar_t cl_decals_bias;
11371 extern cvar_t cl_decals_models;
11372 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11373 // baseparms, parms, temps
11374 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)
11375 {
11376         int cornerindex;
11377         int index;
11378         float v[9][3];
11379         const float *vertex3f;
11380         const float *normal3f;
11381         int numpoints;
11382         float points[2][9][3];
11383         float temp[3];
11384         float tc[9][2];
11385         float f;
11386         float c[9][4];
11387         const int *e;
11388
11389         e = rsurface.modelelement3i + 3*triangleindex;
11390
11391         vertex3f = rsurface.modelvertex3f;
11392         normal3f = rsurface.modelnormal3f;
11393
11394         if (normal3f)
11395         {
11396                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11397                 {
11398                         index = 3*e[cornerindex];
11399                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11400                 }
11401         }
11402         else
11403         {
11404                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11405                 {
11406                         index = 3*e[cornerindex];
11407                         VectorCopy(vertex3f + index, v[cornerindex]);
11408                 }
11409         }
11410
11411         // cull backfaces
11412         //TriangleNormal(v[0], v[1], v[2], normal);
11413         //if (DotProduct(normal, localnormal) < 0.0f)
11414         //      continue;
11415         // clip by each of the box planes formed from the projection matrix
11416         // if anything survives, we emit the decal
11417         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]);
11418         if (numpoints < 3)
11419                 return;
11420         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]);
11421         if (numpoints < 3)
11422                 return;
11423         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]);
11424         if (numpoints < 3)
11425                 return;
11426         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]);
11427         if (numpoints < 3)
11428                 return;
11429         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]);
11430         if (numpoints < 3)
11431                 return;
11432         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]);
11433         if (numpoints < 3)
11434                 return;
11435         // some part of the triangle survived, so we have to accept it...
11436         if (dynamic)
11437         {
11438                 // dynamic always uses the original triangle
11439                 numpoints = 3;
11440                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11441                 {
11442                         index = 3*e[cornerindex];
11443                         VectorCopy(vertex3f + index, v[cornerindex]);
11444                 }
11445         }
11446         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11447         {
11448                 // convert vertex positions to texcoords
11449                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11450                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11451                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11452                 // calculate distance fade from the projection origin
11453                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11454                 f = bound(0.0f, f, 1.0f);
11455                 c[cornerindex][0] = r * f;
11456                 c[cornerindex][1] = g * f;
11457                 c[cornerindex][2] = b * f;
11458                 c[cornerindex][3] = 1.0f;
11459                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11460         }
11461         if (dynamic)
11462                 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);
11463         else
11464                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11465                         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);
11466 }
11467 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)
11468 {
11469         matrix4x4_t projection;
11470         decalsystem_t *decalsystem;
11471         qboolean dynamic;
11472         dp_model_t *model;
11473         const msurface_t *surface;
11474         const msurface_t *surfaces;
11475         const int *surfacelist;
11476         const texture_t *texture;
11477         int numtriangles;
11478         int numsurfacelist;
11479         int surfacelistindex;
11480         int surfaceindex;
11481         int triangleindex;
11482         float localorigin[3];
11483         float localnormal[3];
11484         float localmins[3];
11485         float localmaxs[3];
11486         float localsize;
11487         //float normal[3];
11488         float planes[6][4];
11489         float angles[3];
11490         bih_t *bih;
11491         int bih_triangles_count;
11492         int bih_triangles[256];
11493         int bih_surfaces[256];
11494
11495         decalsystem = &ent->decalsystem;
11496         model = ent->model;
11497         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11498         {
11499                 R_DecalSystem_Reset(&ent->decalsystem);
11500                 return;
11501         }
11502
11503         if (!model->brush.data_leafs && !cl_decals_models.integer)
11504         {
11505                 if (decalsystem->model)
11506                         R_DecalSystem_Reset(decalsystem);
11507                 return;
11508         }
11509
11510         if (decalsystem->model != model)
11511                 R_DecalSystem_Reset(decalsystem);
11512         decalsystem->model = model;
11513
11514         RSurf_ActiveModelEntity(ent, true, false, false);
11515
11516         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11517         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11518         VectorNormalize(localnormal);
11519         localsize = worldsize*rsurface.inversematrixscale;
11520         localmins[0] = localorigin[0] - localsize;
11521         localmins[1] = localorigin[1] - localsize;
11522         localmins[2] = localorigin[2] - localsize;
11523         localmaxs[0] = localorigin[0] + localsize;
11524         localmaxs[1] = localorigin[1] + localsize;
11525         localmaxs[2] = localorigin[2] + localsize;
11526
11527         //VectorCopy(localnormal, planes[4]);
11528         //VectorVectors(planes[4], planes[2], planes[0]);
11529         AnglesFromVectors(angles, localnormal, NULL, false);
11530         AngleVectors(angles, planes[0], planes[2], planes[4]);
11531         VectorNegate(planes[0], planes[1]);
11532         VectorNegate(planes[2], planes[3]);
11533         VectorNegate(planes[4], planes[5]);
11534         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11535         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11536         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11537         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11538         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11539         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11540
11541 #if 1
11542 // works
11543 {
11544         matrix4x4_t forwardprojection;
11545         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11546         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11547 }
11548 #else
11549 // broken
11550 {
11551         float projectionvector[4][3];
11552         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11553         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11554         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11555         projectionvector[0][0] = planes[0][0] * ilocalsize;
11556         projectionvector[0][1] = planes[1][0] * ilocalsize;
11557         projectionvector[0][2] = planes[2][0] * ilocalsize;
11558         projectionvector[1][0] = planes[0][1] * ilocalsize;
11559         projectionvector[1][1] = planes[1][1] * ilocalsize;
11560         projectionvector[1][2] = planes[2][1] * ilocalsize;
11561         projectionvector[2][0] = planes[0][2] * ilocalsize;
11562         projectionvector[2][1] = planes[1][2] * ilocalsize;
11563         projectionvector[2][2] = planes[2][2] * ilocalsize;
11564         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11565         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11566         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11567         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11568 }
11569 #endif
11570
11571         dynamic = model->surfmesh.isanimated;
11572         numsurfacelist = model->nummodelsurfaces;
11573         surfacelist = model->sortedmodelsurfaces;
11574         surfaces = model->data_surfaces;
11575
11576         bih = NULL;
11577         bih_triangles_count = -1;
11578         if(!dynamic)
11579         {
11580                 if(model->render_bih.numleafs)
11581                         bih = &model->render_bih;
11582                 else if(model->collision_bih.numleafs)
11583                         bih = &model->collision_bih;
11584         }
11585         if(bih)
11586                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11587         if(bih_triangles_count == 0)
11588                 return;
11589         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11590                 return;
11591         if(bih_triangles_count > 0)
11592         {
11593                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11594                 {
11595                         surfaceindex = bih_surfaces[triangleindex];
11596                         surface = surfaces + surfaceindex;
11597                         texture = surface->texture;
11598                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11599                                 continue;
11600                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11601                                 continue;
11602                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11603                 }
11604         }
11605         else
11606         {
11607                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11608                 {
11609                         surfaceindex = surfacelist[surfacelistindex];
11610                         surface = surfaces + surfaceindex;
11611                         // check cull box first because it rejects more than any other check
11612                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11613                                 continue;
11614                         // skip transparent surfaces
11615                         texture = surface->texture;
11616                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11617                                 continue;
11618                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11619                                 continue;
11620                         numtriangles = surface->num_triangles;
11621                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11622                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11623                 }
11624         }
11625 }
11626
11627 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11628 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)
11629 {
11630         int renderentityindex;
11631         float worldmins[3];
11632         float worldmaxs[3];
11633         entity_render_t *ent;
11634
11635         if (!cl_decals_newsystem.integer)
11636                 return;
11637
11638         worldmins[0] = worldorigin[0] - worldsize;
11639         worldmins[1] = worldorigin[1] - worldsize;
11640         worldmins[2] = worldorigin[2] - worldsize;
11641         worldmaxs[0] = worldorigin[0] + worldsize;
11642         worldmaxs[1] = worldorigin[1] + worldsize;
11643         worldmaxs[2] = worldorigin[2] + worldsize;
11644
11645         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11646
11647         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11648         {
11649                 ent = r_refdef.scene.entities[renderentityindex];
11650                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11651                         continue;
11652
11653                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11654         }
11655 }
11656
11657 typedef struct r_decalsystem_splatqueue_s
11658 {
11659         vec3_t worldorigin;
11660         vec3_t worldnormal;
11661         float color[4];
11662         float tcrange[4];
11663         float worldsize;
11664         int decalsequence;
11665 }
11666 r_decalsystem_splatqueue_t;
11667
11668 int r_decalsystem_numqueued = 0;
11669 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11670
11671 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)
11672 {
11673         r_decalsystem_splatqueue_t *queue;
11674
11675         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11676                 return;
11677
11678         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11679         VectorCopy(worldorigin, queue->worldorigin);
11680         VectorCopy(worldnormal, queue->worldnormal);
11681         Vector4Set(queue->color, r, g, b, a);
11682         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11683         queue->worldsize = worldsize;
11684         queue->decalsequence = cl.decalsequence++;
11685 }
11686
11687 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11688 {
11689         int i;
11690         r_decalsystem_splatqueue_t *queue;
11691
11692         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11693                 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);
11694         r_decalsystem_numqueued = 0;
11695 }
11696
11697 extern cvar_t cl_decals_max;
11698 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11699 {
11700         int i;
11701         decalsystem_t *decalsystem = &ent->decalsystem;
11702         int numdecals;
11703         int killsequence;
11704         tridecal_t *decal;
11705         float frametime;
11706         float lifetime;
11707
11708         if (!decalsystem->numdecals)
11709                 return;
11710
11711         if (r_showsurfaces.integer)
11712                 return;
11713
11714         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11715         {
11716                 R_DecalSystem_Reset(decalsystem);
11717                 return;
11718         }
11719
11720         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11721         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11722
11723         if (decalsystem->lastupdatetime)
11724                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11725         else
11726                 frametime = 0;
11727         decalsystem->lastupdatetime = r_refdef.scene.time;
11728         numdecals = decalsystem->numdecals;
11729
11730         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11731         {
11732                 if (decal->color4f[0][3])
11733                 {
11734                         decal->lived += frametime;
11735                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11736                         {
11737                                 memset(decal, 0, sizeof(*decal));
11738                                 if (decalsystem->freedecal > i)
11739                                         decalsystem->freedecal = i;
11740                         }
11741                 }
11742         }
11743         decal = decalsystem->decals;
11744         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11745                 numdecals--;
11746
11747         // collapse the array by shuffling the tail decals into the gaps
11748         for (;;)
11749         {
11750                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11751                         decalsystem->freedecal++;
11752                 if (decalsystem->freedecal == numdecals)
11753                         break;
11754                 decal[decalsystem->freedecal] = decal[--numdecals];
11755         }
11756
11757         decalsystem->numdecals = numdecals;
11758
11759         if (numdecals <= 0)
11760         {
11761                 // if there are no decals left, reset decalsystem
11762                 R_DecalSystem_Reset(decalsystem);
11763         }
11764 }
11765
11766 extern skinframe_t *decalskinframe;
11767 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11768 {
11769         int i;
11770         decalsystem_t *decalsystem = &ent->decalsystem;
11771         int numdecals;
11772         tridecal_t *decal;
11773         float faderate;
11774         float alpha;
11775         float *v3f;
11776         float *c4f;
11777         float *t2f;
11778         const int *e;
11779         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11780         int numtris = 0;
11781
11782         numdecals = decalsystem->numdecals;
11783         if (!numdecals)
11784                 return;
11785
11786         if (r_showsurfaces.integer)
11787                 return;
11788
11789         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11790         {
11791                 R_DecalSystem_Reset(decalsystem);
11792                 return;
11793         }
11794
11795         // if the model is static it doesn't matter what value we give for
11796         // wantnormals and wanttangents, so this logic uses only rules applicable
11797         // to a model, knowing that they are meaningless otherwise
11798         if (ent == r_refdef.scene.worldentity)
11799                 RSurf_ActiveWorldEntity();
11800         else
11801                 RSurf_ActiveModelEntity(ent, false, false, false);
11802
11803         decalsystem->lastupdatetime = r_refdef.scene.time;
11804
11805         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11806
11807         // update vertex positions for animated models
11808         v3f = decalsystem->vertex3f;
11809         c4f = decalsystem->color4f;
11810         t2f = decalsystem->texcoord2f;
11811         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11812         {
11813                 if (!decal->color4f[0][3])
11814                         continue;
11815
11816                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11817                         continue;
11818
11819                 // skip backfaces
11820                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11821                         continue;
11822
11823                 // update color values for fading decals
11824                 if (decal->lived >= cl_decals_time.value)
11825                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11826                 else
11827                         alpha = 1.0f;
11828
11829                 c4f[ 0] = decal->color4f[0][0] * alpha;
11830                 c4f[ 1] = decal->color4f[0][1] * alpha;
11831                 c4f[ 2] = decal->color4f[0][2] * alpha;
11832                 c4f[ 3] = 1;
11833                 c4f[ 4] = decal->color4f[1][0] * alpha;
11834                 c4f[ 5] = decal->color4f[1][1] * alpha;
11835                 c4f[ 6] = decal->color4f[1][2] * alpha;
11836                 c4f[ 7] = 1;
11837                 c4f[ 8] = decal->color4f[2][0] * alpha;
11838                 c4f[ 9] = decal->color4f[2][1] * alpha;
11839                 c4f[10] = decal->color4f[2][2] * alpha;
11840                 c4f[11] = 1;
11841
11842                 t2f[0] = decal->texcoord2f[0][0];
11843                 t2f[1] = decal->texcoord2f[0][1];
11844                 t2f[2] = decal->texcoord2f[1][0];
11845                 t2f[3] = decal->texcoord2f[1][1];
11846                 t2f[4] = decal->texcoord2f[2][0];
11847                 t2f[5] = decal->texcoord2f[2][1];
11848
11849                 // update vertex positions for animated models
11850                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11851                 {
11852                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11853                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11854                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11855                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11856                 }
11857                 else
11858                 {
11859                         VectorCopy(decal->vertex3f[0], v3f);
11860                         VectorCopy(decal->vertex3f[1], v3f + 3);
11861                         VectorCopy(decal->vertex3f[2], v3f + 6);
11862                 }
11863
11864                 if (r_refdef.fogenabled)
11865                 {
11866                         alpha = RSurf_FogVertex(v3f);
11867                         VectorScale(c4f, alpha, c4f);
11868                         alpha = RSurf_FogVertex(v3f + 3);
11869                         VectorScale(c4f + 4, alpha, c4f + 4);
11870                         alpha = RSurf_FogVertex(v3f + 6);
11871                         VectorScale(c4f + 8, alpha, c4f + 8);
11872                 }
11873
11874                 v3f += 9;
11875                 c4f += 12;
11876                 t2f += 6;
11877                 numtris++;
11878         }
11879
11880         if (numtris > 0)
11881         {
11882                 r_refdef.stats[r_stat_drawndecals] += numtris;
11883
11884                 // now render the decals all at once
11885                 // (this assumes they all use one particle font texture!)
11886                 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);
11887 //              R_Mesh_ResetTextureState();
11888                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11889                 GL_DepthMask(false);
11890                 GL_DepthRange(0, 1);
11891                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11892                 GL_DepthTest(true);
11893                 GL_CullFace(GL_NONE);
11894                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11895                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11896                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11897         }
11898 }
11899
11900 static void R_DrawModelDecals(void)
11901 {
11902         int i, numdecals;
11903
11904         // fade faster when there are too many decals
11905         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11906         for (i = 0;i < r_refdef.scene.numentities;i++)
11907                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11908
11909         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11910         for (i = 0;i < r_refdef.scene.numentities;i++)
11911                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11912                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11913
11914         R_DecalSystem_ApplySplatEntitiesQueue();
11915
11916         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11917         for (i = 0;i < r_refdef.scene.numentities;i++)
11918                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11919
11920         r_refdef.stats[r_stat_totaldecals] += numdecals;
11921
11922         if (r_showsurfaces.integer)
11923                 return;
11924
11925         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11926
11927         for (i = 0;i < r_refdef.scene.numentities;i++)
11928         {
11929                 if (!r_refdef.viewcache.entityvisible[i])
11930                         continue;
11931                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11932                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11933         }
11934 }
11935
11936 extern cvar_t mod_collision_bih;
11937 static void R_DrawDebugModel(void)
11938 {
11939         entity_render_t *ent = rsurface.entity;
11940         int i, j, k, l, flagsmask;
11941         const msurface_t *surface;
11942         dp_model_t *model = ent->model;
11943         vec3_t v;
11944
11945         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11946                 return;
11947
11948         if (r_showoverdraw.value > 0)
11949         {
11950                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11951                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11952                 R_SetupShader_Generic_NoTexture(false, false);
11953                 GL_DepthTest(false);
11954                 GL_DepthMask(false);
11955                 GL_DepthRange(0, 1);
11956                 GL_BlendFunc(GL_ONE, GL_ONE);
11957                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11958                 {
11959                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11960                                 continue;
11961                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11962                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11963                         {
11964                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11965                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11966                                 if (!rsurface.texture->currentlayers->depthmask)
11967                                         GL_Color(c, 0, 0, 1.0f);
11968                                 else if (ent == r_refdef.scene.worldentity)
11969                                         GL_Color(c, c, c, 1.0f);
11970                                 else
11971                                         GL_Color(0, c, 0, 1.0f);
11972                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11973                                 RSurf_DrawBatch();
11974                         }
11975                 }
11976                 rsurface.texture = NULL;
11977         }
11978
11979         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11980
11981 //      R_Mesh_ResetTextureState();
11982         R_SetupShader_Generic_NoTexture(false, false);
11983         GL_DepthRange(0, 1);
11984         GL_DepthTest(!r_showdisabledepthtest.integer);
11985         GL_DepthMask(false);
11986         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11987
11988         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11989         {
11990                 int triangleindex;
11991                 int bihleafindex;
11992                 qboolean cullbox = false;
11993                 const q3mbrush_t *brush;
11994                 const bih_t *bih = &model->collision_bih;
11995                 const bih_leaf_t *bihleaf;
11996                 float vertex3f[3][3];
11997                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11998                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11999                 {
12000                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12001                                 continue;
12002                         switch (bihleaf->type)
12003                         {
12004                         case BIH_BRUSH:
12005                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12006                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12007                                 {
12008                                         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);
12009                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12010                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12011                                 }
12012                                 break;
12013                         case BIH_COLLISIONTRIANGLE:
12014                                 triangleindex = bihleaf->itemindex;
12015                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12016                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12017                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12018                                 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);
12019                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12020                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12021                                 break;
12022                         case BIH_RENDERTRIANGLE:
12023                                 triangleindex = bihleaf->itemindex;
12024                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12025                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12026                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12027                                 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);
12028                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12029                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12030                                 break;
12031                         }
12032                 }
12033         }
12034
12035         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12036
12037 #ifndef USE_GLES2
12038         if (r_showtris.integer && qglPolygonMode)
12039         {
12040                 if (r_showdisabledepthtest.integer)
12041                 {
12042                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12043                         GL_DepthMask(false);
12044                 }
12045                 else
12046                 {
12047                         GL_BlendFunc(GL_ONE, GL_ZERO);
12048                         GL_DepthMask(true);
12049                 }
12050                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12051                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12052                 {
12053                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12054                                 continue;
12055                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12056                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12057                         {
12058                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12059                                 if (!rsurface.texture->currentlayers->depthmask)
12060                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12061                                 else if (ent == r_refdef.scene.worldentity)
12062                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12063                                 else
12064                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12065                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12066                                 RSurf_DrawBatch();
12067                         }
12068                 }
12069                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12070                 rsurface.texture = NULL;
12071         }
12072
12073         if (r_shownormals.value != 0 && qglBegin)
12074         {
12075                 if (r_showdisabledepthtest.integer)
12076                 {
12077                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12078                         GL_DepthMask(false);
12079                 }
12080                 else
12081                 {
12082                         GL_BlendFunc(GL_ONE, GL_ZERO);
12083                         GL_DepthMask(true);
12084                 }
12085                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12086                 {
12087                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12088                                 continue;
12089                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12090                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12091                         {
12092                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12093                                 qglBegin(GL_LINES);
12094                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12095                                 {
12096                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12097                                         {
12098                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12099                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12100                                                 qglVertex3f(v[0], v[1], v[2]);
12101                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12102                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12103                                                 qglVertex3f(v[0], v[1], v[2]);
12104                                         }
12105                                 }
12106                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12107                                 {
12108                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12109                                         {
12110                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12111                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12112                                                 qglVertex3f(v[0], v[1], v[2]);
12113                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12114                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12115                                                 qglVertex3f(v[0], v[1], v[2]);
12116                                         }
12117                                 }
12118                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12119                                 {
12120                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12121                                         {
12122                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12123                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12124                                                 qglVertex3f(v[0], v[1], v[2]);
12125                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12126                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12127                                                 qglVertex3f(v[0], v[1], v[2]);
12128                                         }
12129                                 }
12130                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12131                                 {
12132                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12133                                         {
12134                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12135                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12136                                                 qglVertex3f(v[0], v[1], v[2]);
12137                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12138                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12139                                                 qglVertex3f(v[0], v[1], v[2]);
12140                                         }
12141                                 }
12142                                 qglEnd();
12143                                 CHECKGLERROR
12144                         }
12145                 }
12146                 rsurface.texture = NULL;
12147         }
12148 #endif
12149 }
12150
12151 int r_maxsurfacelist = 0;
12152 const msurface_t **r_surfacelist = NULL;
12153 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12154 {
12155         int i, j, endj, flagsmask;
12156         dp_model_t *model = r_refdef.scene.worldmodel;
12157         msurface_t *surfaces;
12158         unsigned char *update;
12159         int numsurfacelist = 0;
12160         if (model == NULL)
12161                 return;
12162
12163         if (r_maxsurfacelist < model->num_surfaces)
12164         {
12165                 r_maxsurfacelist = model->num_surfaces;
12166                 if (r_surfacelist)
12167                         Mem_Free((msurface_t**)r_surfacelist);
12168                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12169         }
12170
12171         RSurf_ActiveWorldEntity();
12172
12173         surfaces = model->data_surfaces;
12174         update = model->brushq1.lightmapupdateflags;
12175
12176         // update light styles on this submodel
12177         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12178         {
12179                 model_brush_lightstyleinfo_t *style;
12180                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12181                 {
12182                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12183                         {
12184                                 int *list = style->surfacelist;
12185                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12186                                 for (j = 0;j < style->numsurfaces;j++)
12187                                         update[list[j]] = true;
12188                         }
12189                 }
12190         }
12191
12192         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12193
12194         if (debug)
12195         {
12196                 R_DrawDebugModel();
12197                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12198                 return;
12199         }
12200
12201         rsurface.lightmaptexture = NULL;
12202         rsurface.deluxemaptexture = NULL;
12203         rsurface.uselightmaptexture = false;
12204         rsurface.texture = NULL;
12205         rsurface.rtlight = NULL;
12206         numsurfacelist = 0;
12207         // add visible surfaces to draw list
12208         for (i = 0;i < model->nummodelsurfaces;i++)
12209         {
12210                 j = model->sortedmodelsurfaces[i];
12211                 if (r_refdef.viewcache.world_surfacevisible[j])
12212                         r_surfacelist[numsurfacelist++] = surfaces + j;
12213         }
12214         // update lightmaps if needed
12215         if (model->brushq1.firstrender)
12216         {
12217                 model->brushq1.firstrender = false;
12218                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12219                         if (update[j])
12220                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12221         }
12222         else if (update)
12223         {
12224                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12225                         if (r_refdef.viewcache.world_surfacevisible[j])
12226                                 if (update[j])
12227                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12228         }
12229         // don't do anything if there were no surfaces
12230         if (!numsurfacelist)
12231         {
12232                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12233                 return;
12234         }
12235         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12236
12237         // add to stats if desired
12238         if (r_speeds.integer && !skysurfaces && !depthonly)
12239         {
12240                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12241                 for (j = 0;j < numsurfacelist;j++)
12242                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12243         }
12244
12245         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12246 }
12247
12248 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12249 {
12250         int i, j, endj, flagsmask;
12251         dp_model_t *model = ent->model;
12252         msurface_t *surfaces;
12253         unsigned char *update;
12254         int numsurfacelist = 0;
12255         if (model == NULL)
12256                 return;
12257
12258         if (r_maxsurfacelist < model->num_surfaces)
12259         {
12260                 r_maxsurfacelist = model->num_surfaces;
12261                 if (r_surfacelist)
12262                         Mem_Free((msurface_t **)r_surfacelist);
12263                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12264         }
12265
12266         // if the model is static it doesn't matter what value we give for
12267         // wantnormals and wanttangents, so this logic uses only rules applicable
12268         // to a model, knowing that they are meaningless otherwise
12269         if (ent == r_refdef.scene.worldentity)
12270                 RSurf_ActiveWorldEntity();
12271         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12272                 RSurf_ActiveModelEntity(ent, false, false, false);
12273         else if (prepass)
12274                 RSurf_ActiveModelEntity(ent, true, true, true);
12275         else if (depthonly)
12276         {
12277                 switch (vid.renderpath)
12278                 {
12279                 case RENDERPATH_GL20:
12280                 case RENDERPATH_D3D9:
12281                 case RENDERPATH_D3D10:
12282                 case RENDERPATH_D3D11:
12283                 case RENDERPATH_SOFT:
12284                 case RENDERPATH_GLES2:
12285                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12286                         break;
12287                 case RENDERPATH_GL11:
12288                 case RENDERPATH_GL13:
12289                 case RENDERPATH_GLES1:
12290                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12291                         break;
12292                 }
12293         }
12294         else
12295         {
12296                 switch (vid.renderpath)
12297                 {
12298                 case RENDERPATH_GL20:
12299                 case RENDERPATH_D3D9:
12300                 case RENDERPATH_D3D10:
12301                 case RENDERPATH_D3D11:
12302                 case RENDERPATH_SOFT:
12303                 case RENDERPATH_GLES2:
12304                         RSurf_ActiveModelEntity(ent, true, true, false);
12305                         break;
12306                 case RENDERPATH_GL11:
12307                 case RENDERPATH_GL13:
12308                 case RENDERPATH_GLES1:
12309                         RSurf_ActiveModelEntity(ent, true, false, false);
12310                         break;
12311                 }
12312         }
12313
12314         surfaces = model->data_surfaces;
12315         update = model->brushq1.lightmapupdateflags;
12316
12317         // update light styles
12318         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12319         {
12320                 model_brush_lightstyleinfo_t *style;
12321                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12322                 {
12323                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12324                         {
12325                                 int *list = style->surfacelist;
12326                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12327                                 for (j = 0;j < style->numsurfaces;j++)
12328                                         update[list[j]] = true;
12329                         }
12330                 }
12331         }
12332
12333         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12334
12335         if (debug)
12336         {
12337                 R_DrawDebugModel();
12338                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12339                 return;
12340         }
12341
12342         rsurface.lightmaptexture = NULL;
12343         rsurface.deluxemaptexture = NULL;
12344         rsurface.uselightmaptexture = false;
12345         rsurface.texture = NULL;
12346         rsurface.rtlight = NULL;
12347         numsurfacelist = 0;
12348         // add visible surfaces to draw list
12349         for (i = 0;i < model->nummodelsurfaces;i++)
12350                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12351         // don't do anything if there were no surfaces
12352         if (!numsurfacelist)
12353         {
12354                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12355                 return;
12356         }
12357         // update lightmaps if needed
12358         if (update)
12359         {
12360                 int updated = 0;
12361                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12362                 {
12363                         if (update[j])
12364                         {
12365                                 updated++;
12366                                 R_BuildLightMap(ent, surfaces + j);
12367                         }
12368                 }
12369         }
12370
12371         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12372
12373         // add to stats if desired
12374         if (r_speeds.integer && !skysurfaces && !depthonly)
12375         {
12376                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12377                 for (j = 0;j < numsurfacelist;j++)
12378                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12379         }
12380
12381         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12382 }
12383
12384 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12385 {
12386         static texture_t texture;
12387         static msurface_t surface;
12388         const msurface_t *surfacelist = &surface;
12389
12390         // fake enough texture and surface state to render this geometry
12391
12392         texture.update_lastrenderframe = -1; // regenerate this texture
12393         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12394         texture.currentskinframe = skinframe;
12395         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12396         texture.offsetmapping = OFFSETMAPPING_OFF;
12397         texture.offsetscale = 1;
12398         texture.specularscalemod = 1;
12399         texture.specularpowermod = 1;
12400         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12401         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12402         // JUST GREP FOR "specularscalemod = 1".
12403
12404         surface.texture = &texture;
12405         surface.num_triangles = numtriangles;
12406         surface.num_firsttriangle = firsttriangle;
12407         surface.num_vertices = numvertices;
12408         surface.num_firstvertex = firstvertex;
12409
12410         // now render it
12411         rsurface.texture = R_GetCurrentTexture(surface.texture);
12412         rsurface.lightmaptexture = NULL;
12413         rsurface.deluxemaptexture = NULL;
12414         rsurface.uselightmaptexture = false;
12415         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12416 }
12417
12418 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)
12419 {
12420         static msurface_t surface;
12421         const msurface_t *surfacelist = &surface;
12422
12423         // fake enough texture and surface state to render this geometry
12424         surface.texture = texture;
12425         surface.num_triangles = numtriangles;
12426         surface.num_firsttriangle = firsttriangle;
12427         surface.num_vertices = numvertices;
12428         surface.num_firstvertex = firstvertex;
12429
12430         // now render it
12431         rsurface.texture = R_GetCurrentTexture(surface.texture);
12432         rsurface.lightmaptexture = NULL;
12433         rsurface.deluxemaptexture = NULL;
12434         rsurface.uselightmaptexture = false;
12435         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12436 }