]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Nevermind, we can't remove that STX char... just add \{3} for our purposes
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47 static qboolean r_gpuskeletal;
48
49 //
50 // screen size info
51 //
52 r_refdef_t r_refdef;
53
54 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
55 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
56 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
57 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
58 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
60 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
61 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
62 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
63 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
64 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
65 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
66
67 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
68 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
69 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
70 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
71 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
72
73 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
74 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
75 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
76 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
77 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
78 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
79 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
80 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
81 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
82 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
83 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
84 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
85 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
86 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
87 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
88 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
89 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
90 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
91 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
92 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
93 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
94 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
95 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
96 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
97 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
98 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
99 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
100 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
101 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
102 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
103 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
104 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
105 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
106 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
107 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
108
109 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
110 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
111 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
112
113 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
114 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
115 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
116 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
117 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
118 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
119 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
120 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
121 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
122 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
123 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
124 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
125 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
126 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
127 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
128 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
130 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
131 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
132 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
133 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
134 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
135 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
136 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
137 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
138 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
139
140 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
141 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
142 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
143 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
144 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
145 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
146 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
147 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
148
149 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
150 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
151
152 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
153 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
154 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
155
156 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
157 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
158 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
159 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
160 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
161 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
162 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
163 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
164 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
165
166 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
167 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
168 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
169 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
170 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
171 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
172 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
173 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
174 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
175 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
176 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
177 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
178 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
179 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
180 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
181 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
182 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
183 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
184 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
185
186 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
187 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
188 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
189 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
190 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
191 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
192 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
193 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
194 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
195
196 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
197 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
198 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
199 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
200
201 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
202 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
203
204 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
205 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
206 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
207 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
208 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
209 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
210
211 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
212 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
213 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
214 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
215 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
217 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
218 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
219 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
220 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
221
222 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
223
224 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
225
226 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
227
228 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
229
230 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
231 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
232 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
233
234 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
235 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
236
237 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
238
239 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
240
241 extern cvar_t v_glslgamma;
242 extern cvar_t v_glslgamma_2d;
243
244 extern qboolean v_flipped_state;
245
246 r_framebufferstate_t r_fb;
247
248 /// shadow volume bsp struct with automatically growing nodes buffer
249 svbsp_t r_svbsp;
250
251 rtexture_t *r_texture_blanknormalmap;
252 rtexture_t *r_texture_white;
253 rtexture_t *r_texture_grey128;
254 rtexture_t *r_texture_black;
255 rtexture_t *r_texture_notexture;
256 rtexture_t *r_texture_whitecube;
257 rtexture_t *r_texture_normalizationcube;
258 rtexture_t *r_texture_fogattenuation;
259 rtexture_t *r_texture_fogheighttexture;
260 rtexture_t *r_texture_gammaramps;
261 unsigned int r_texture_gammaramps_serial;
262 //rtexture_t *r_texture_fogintensity;
263 rtexture_t *r_texture_reflectcube;
264
265 // TODO: hash lookups?
266 typedef struct cubemapinfo_s
267 {
268         char basename[64];
269         rtexture_t *texture;
270 }
271 cubemapinfo_t;
272
273 int r_texture_numcubemaps;
274 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
275
276 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
277 unsigned int r_numqueries;
278 unsigned int r_maxqueries;
279
280 typedef struct r_qwskincache_s
281 {
282         char name[MAX_QPATH];
283         skinframe_t *skinframe;
284 }
285 r_qwskincache_t;
286
287 static r_qwskincache_t *r_qwskincache;
288 static int r_qwskincache_size;
289
290 /// vertex coordinates for a quad that covers the screen exactly
291 extern const float r_screenvertex3f[12];
292 extern const float r_d3dscreenvertex3f[12];
293 const float r_screenvertex3f[12] =
294 {
295         0, 0, 0,
296         1, 0, 0,
297         1, 1, 0,
298         0, 1, 0
299 };
300 const float r_d3dscreenvertex3f[12] =
301 {
302         0, 1, 0,
303         1, 1, 0,
304         1, 0, 0,
305         0, 0, 0
306 };
307
308 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
309 {
310         int i;
311         for (i = 0;i < verts;i++)
312         {
313                 out[0] = in[0] * r;
314                 out[1] = in[1] * g;
315                 out[2] = in[2] * b;
316                 out[3] = in[3];
317                 in += 4;
318                 out += 4;
319         }
320 }
321
322 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
323 {
324         int i;
325         for (i = 0;i < verts;i++)
326         {
327                 out[0] = r;
328                 out[1] = g;
329                 out[2] = b;
330                 out[3] = a;
331                 out += 4;
332         }
333 }
334
335 // FIXME: move this to client?
336 void FOG_clear(void)
337 {
338         if (gamemode == GAME_NEHAHRA)
339         {
340                 Cvar_Set("gl_fogenable", "0");
341                 Cvar_Set("gl_fogdensity", "0.2");
342                 Cvar_Set("gl_fogred", "0.3");
343                 Cvar_Set("gl_foggreen", "0.3");
344                 Cvar_Set("gl_fogblue", "0.3");
345         }
346         r_refdef.fog_density = 0;
347         r_refdef.fog_red = 0;
348         r_refdef.fog_green = 0;
349         r_refdef.fog_blue = 0;
350         r_refdef.fog_alpha = 1;
351         r_refdef.fog_start = 0;
352         r_refdef.fog_end = 16384;
353         r_refdef.fog_height = 1<<30;
354         r_refdef.fog_fadedepth = 128;
355         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
356 }
357
358 static void R_BuildBlankTextures(void)
359 {
360         unsigned char data[4];
361         data[2] = 128; // normal X
362         data[1] = 128; // normal Y
363         data[0] = 255; // normal Z
364         data[3] = 255; // height
365         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
366         data[0] = 255;
367         data[1] = 255;
368         data[2] = 255;
369         data[3] = 255;
370         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
371         data[0] = 128;
372         data[1] = 128;
373         data[2] = 128;
374         data[3] = 255;
375         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376         data[0] = 0;
377         data[1] = 0;
378         data[2] = 0;
379         data[3] = 255;
380         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381 }
382
383 static void R_BuildNoTexture(void)
384 {
385         int x, y;
386         unsigned char pix[16][16][4];
387         // this makes a light grey/dark grey checkerboard texture
388         for (y = 0;y < 16;y++)
389         {
390                 for (x = 0;x < 16;x++)
391                 {
392                         if ((y < 8) ^ (x < 8))
393                         {
394                                 pix[y][x][0] = 128;
395                                 pix[y][x][1] = 128;
396                                 pix[y][x][2] = 128;
397                                 pix[y][x][3] = 255;
398                         }
399                         else
400                         {
401                                 pix[y][x][0] = 64;
402                                 pix[y][x][1] = 64;
403                                 pix[y][x][2] = 64;
404                                 pix[y][x][3] = 255;
405                         }
406                 }
407         }
408         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
409 }
410
411 static void R_BuildWhiteCube(void)
412 {
413         unsigned char data[6*1*1*4];
414         memset(data, 255, sizeof(data));
415         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
416 }
417
418 static void R_BuildNormalizationCube(void)
419 {
420         int x, y, side;
421         vec3_t v;
422         vec_t s, t, intensity;
423 #define NORMSIZE 64
424         unsigned char *data;
425         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
426         for (side = 0;side < 6;side++)
427         {
428                 for (y = 0;y < NORMSIZE;y++)
429                 {
430                         for (x = 0;x < NORMSIZE;x++)
431                         {
432                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
433                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
434                                 switch(side)
435                                 {
436                                 default:
437                                 case 0:
438                                         v[0] = 1;
439                                         v[1] = -t;
440                                         v[2] = -s;
441                                         break;
442                                 case 1:
443                                         v[0] = -1;
444                                         v[1] = -t;
445                                         v[2] = s;
446                                         break;
447                                 case 2:
448                                         v[0] = s;
449                                         v[1] = 1;
450                                         v[2] = t;
451                                         break;
452                                 case 3:
453                                         v[0] = s;
454                                         v[1] = -1;
455                                         v[2] = -t;
456                                         break;
457                                 case 4:
458                                         v[0] = s;
459                                         v[1] = -t;
460                                         v[2] = 1;
461                                         break;
462                                 case 5:
463                                         v[0] = -s;
464                                         v[1] = -t;
465                                         v[2] = -1;
466                                         break;
467                                 }
468                                 intensity = 127.0f / sqrt(DotProduct(v, v));
469                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
470                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
471                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
472                                 data[((side*64+y)*64+x)*4+3] = 255;
473                         }
474                 }
475         }
476         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
477         Mem_Free(data);
478 }
479
480 static void R_BuildFogTexture(void)
481 {
482         int x, b;
483 #define FOGWIDTH 256
484         unsigned char data1[FOGWIDTH][4];
485         //unsigned char data2[FOGWIDTH][4];
486         double d, r, alpha;
487
488         r_refdef.fogmasktable_start = r_refdef.fog_start;
489         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
490         r_refdef.fogmasktable_range = r_refdef.fogrange;
491         r_refdef.fogmasktable_density = r_refdef.fog_density;
492
493         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
494         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
495         {
496                 d = (x * r - r_refdef.fogmasktable_start);
497                 if(developer_extra.integer)
498                         Con_DPrintf("%f ", d);
499                 d = max(0, d);
500                 if (r_fog_exp2.integer)
501                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
502                 else
503                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
504                 if(developer_extra.integer)
505                         Con_DPrintf(" : %f ", alpha);
506                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
507                 if(developer_extra.integer)
508                         Con_DPrintf(" = %f\n", alpha);
509                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
510         }
511
512         for (x = 0;x < FOGWIDTH;x++)
513         {
514                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
515                 data1[x][0] = b;
516                 data1[x][1] = b;
517                 data1[x][2] = b;
518                 data1[x][3] = 255;
519                 //data2[x][0] = 255 - b;
520                 //data2[x][1] = 255 - b;
521                 //data2[x][2] = 255 - b;
522                 //data2[x][3] = 255;
523         }
524         if (r_texture_fogattenuation)
525         {
526                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
527                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
528         }
529         else
530         {
531                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
532                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
533         }
534 }
535
536 static void R_BuildFogHeightTexture(void)
537 {
538         unsigned char *inpixels;
539         int size;
540         int x;
541         int y;
542         int j;
543         float c[4];
544         float f;
545         inpixels = NULL;
546         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
547         if (r_refdef.fogheighttexturename[0])
548                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
549         if (!inpixels)
550         {
551                 r_refdef.fog_height_tablesize = 0;
552                 if (r_texture_fogheighttexture)
553                         R_FreeTexture(r_texture_fogheighttexture);
554                 r_texture_fogheighttexture = NULL;
555                 if (r_refdef.fog_height_table2d)
556                         Mem_Free(r_refdef.fog_height_table2d);
557                 r_refdef.fog_height_table2d = NULL;
558                 if (r_refdef.fog_height_table1d)
559                         Mem_Free(r_refdef.fog_height_table1d);
560                 r_refdef.fog_height_table1d = NULL;
561                 return;
562         }
563         size = image_width;
564         r_refdef.fog_height_tablesize = size;
565         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
566         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
567         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
568         Mem_Free(inpixels);
569         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
570         // average fog color table accounting for every fog layer between a point
571         // and the camera.  (Note: attenuation is handled separately!)
572         for (y = 0;y < size;y++)
573         {
574                 for (x = 0;x < size;x++)
575                 {
576                         Vector4Clear(c);
577                         f = 0;
578                         if (x < y)
579                         {
580                                 for (j = x;j <= y;j++)
581                                 {
582                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
583                                         f++;
584                                 }
585                         }
586                         else
587                         {
588                                 for (j = x;j >= y;j--)
589                                 {
590                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
591                                         f++;
592                                 }
593                         }
594                         f = 1.0f / f;
595                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
596                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
597                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
598                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
599                 }
600         }
601         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
602 }
603
604 //=======================================================================================================================================================
605
606 static const char *builtinshaderstrings[] =
607 {
608 #include "shader_glsl.h"
609 0
610 };
611
612 const char *builtinhlslshaderstrings[] =
613 {
614 #include "shader_hlsl.h"
615 0
616 };
617
618 char *glslshaderstring = NULL;
619 char *hlslshaderstring = NULL;
620
621 //=======================================================================================================================================================
622
623 typedef struct shaderpermutationinfo_s
624 {
625         const char *pretext;
626         const char *name;
627 }
628 shaderpermutationinfo_t;
629
630 typedef struct shadermodeinfo_s
631 {
632         const char *filename;
633         const char *pretext;
634         const char *name;
635 }
636 shadermodeinfo_t;
637
638 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
639 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
640 {
641         {"#define USEDIFFUSE\n", " diffuse"},
642         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
643         {"#define USEVIEWTINT\n", " viewtint"},
644         {"#define USECOLORMAPPING\n", " colormapping"},
645         {"#define USESATURATION\n", " saturation"},
646         {"#define USEFOGINSIDE\n", " foginside"},
647         {"#define USEFOGOUTSIDE\n", " fogoutside"},
648         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
649         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
650         {"#define USEGAMMARAMPS\n", " gammaramps"},
651         {"#define USECUBEFILTER\n", " cubefilter"},
652         {"#define USEGLOW\n", " glow"},
653         {"#define USEBLOOM\n", " bloom"},
654         {"#define USESPECULAR\n", " specular"},
655         {"#define USEPOSTPROCESSING\n", " postprocessing"},
656         {"#define USEREFLECTION\n", " reflection"},
657         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
658         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
659         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
660         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
661         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
662         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
663         {"#define USEALPHAKILL\n", " alphakill"},
664         {"#define USEREFLECTCUBE\n", " reflectcube"},
665         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
666         {"#define USEBOUNCEGRID\n", " bouncegrid"},
667         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
668         {"#define USETRIPPY\n", " trippy"},
669         {"#define USEDEPTHRGB\n", " depthrgb"},
670         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
671         {"#define USESKELETAL\n", " skeletal"}
672 };
673
674 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
675 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
676 {
677         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
678         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
679         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
680         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
681         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
682         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
683         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
684         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
685         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
686         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
687         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
688         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
689         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
690         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
691         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
692         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
693         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
694 };
695
696 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
697 {
698         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
699         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
700         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
701         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
702         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
703         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
704         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
705         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
706         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
707         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
708         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
709         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
710         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
711         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
712         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
713         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
714         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
715 };
716
717 struct r_glsl_permutation_s;
718 typedef struct r_glsl_permutation_s
719 {
720         /// hash lookup data
721         struct r_glsl_permutation_s *hashnext;
722         unsigned int mode;
723         unsigned int permutation;
724
725         /// indicates if we have tried compiling this permutation already
726         qboolean compiled;
727         /// 0 if compilation failed
728         int program;
729         // texture units assigned to each detected uniform
730         int tex_Texture_First;
731         int tex_Texture_Second;
732         int tex_Texture_GammaRamps;
733         int tex_Texture_Normal;
734         int tex_Texture_Color;
735         int tex_Texture_Gloss;
736         int tex_Texture_Glow;
737         int tex_Texture_SecondaryNormal;
738         int tex_Texture_SecondaryColor;
739         int tex_Texture_SecondaryGloss;
740         int tex_Texture_SecondaryGlow;
741         int tex_Texture_Pants;
742         int tex_Texture_Shirt;
743         int tex_Texture_FogHeightTexture;
744         int tex_Texture_FogMask;
745         int tex_Texture_Lightmap;
746         int tex_Texture_Deluxemap;
747         int tex_Texture_Attenuation;
748         int tex_Texture_Cube;
749         int tex_Texture_Refraction;
750         int tex_Texture_Reflection;
751         int tex_Texture_ShadowMap2D;
752         int tex_Texture_CubeProjection;
753         int tex_Texture_ScreenNormalMap;
754         int tex_Texture_ScreenDiffuse;
755         int tex_Texture_ScreenSpecular;
756         int tex_Texture_ReflectMask;
757         int tex_Texture_ReflectCube;
758         int tex_Texture_BounceGrid;
759         /// locations of detected uniforms in program object, or -1 if not found
760         int loc_Texture_First;
761         int loc_Texture_Second;
762         int loc_Texture_GammaRamps;
763         int loc_Texture_Normal;
764         int loc_Texture_Color;
765         int loc_Texture_Gloss;
766         int loc_Texture_Glow;
767         int loc_Texture_SecondaryNormal;
768         int loc_Texture_SecondaryColor;
769         int loc_Texture_SecondaryGloss;
770         int loc_Texture_SecondaryGlow;
771         int loc_Texture_Pants;
772         int loc_Texture_Shirt;
773         int loc_Texture_FogHeightTexture;
774         int loc_Texture_FogMask;
775         int loc_Texture_Lightmap;
776         int loc_Texture_Deluxemap;
777         int loc_Texture_Attenuation;
778         int loc_Texture_Cube;
779         int loc_Texture_Refraction;
780         int loc_Texture_Reflection;
781         int loc_Texture_ShadowMap2D;
782         int loc_Texture_CubeProjection;
783         int loc_Texture_ScreenNormalMap;
784         int loc_Texture_ScreenDiffuse;
785         int loc_Texture_ScreenSpecular;
786         int loc_Texture_ReflectMask;
787         int loc_Texture_ReflectCube;
788         int loc_Texture_BounceGrid;
789         int loc_Alpha;
790         int loc_BloomBlur_Parameters;
791         int loc_ClientTime;
792         int loc_Color_Ambient;
793         int loc_Color_Diffuse;
794         int loc_Color_Specular;
795         int loc_Color_Glow;
796         int loc_Color_Pants;
797         int loc_Color_Shirt;
798         int loc_DeferredColor_Ambient;
799         int loc_DeferredColor_Diffuse;
800         int loc_DeferredColor_Specular;
801         int loc_DeferredMod_Diffuse;
802         int loc_DeferredMod_Specular;
803         int loc_DistortScaleRefractReflect;
804         int loc_EyePosition;
805         int loc_FogColor;
806         int loc_FogHeightFade;
807         int loc_FogPlane;
808         int loc_FogPlaneViewDist;
809         int loc_FogRangeRecip;
810         int loc_LightColor;
811         int loc_LightDir;
812         int loc_LightPosition;
813         int loc_OffsetMapping_ScaleSteps;
814         int loc_OffsetMapping_LodDistance;
815         int loc_OffsetMapping_Bias;
816         int loc_PixelSize;
817         int loc_ReflectColor;
818         int loc_ReflectFactor;
819         int loc_ReflectOffset;
820         int loc_RefractColor;
821         int loc_Saturation;
822         int loc_ScreenCenterRefractReflect;
823         int loc_ScreenScaleRefractReflect;
824         int loc_ScreenToDepth;
825         int loc_ShadowMap_Parameters;
826         int loc_ShadowMap_TextureScale;
827         int loc_SpecularPower;
828         int loc_Skeletal_Transform12;
829         int loc_UserVec1;
830         int loc_UserVec2;
831         int loc_UserVec3;
832         int loc_UserVec4;
833         int loc_ViewTintColor;
834         int loc_ViewToLight;
835         int loc_ModelToLight;
836         int loc_TexMatrix;
837         int loc_BackgroundTexMatrix;
838         int loc_ModelViewProjectionMatrix;
839         int loc_ModelViewMatrix;
840         int loc_PixelToScreenTexCoord;
841         int loc_ModelToReflectCube;
842         int loc_ShadowMapMatrix;
843         int loc_BloomColorSubtract;
844         int loc_NormalmapScrollBlend;
845         int loc_BounceGridMatrix;
846         int loc_BounceGridIntensity;
847 }
848 r_glsl_permutation_t;
849
850 #define SHADERPERMUTATION_HASHSIZE 256
851
852
853 // non-degradable "lightweight" shader parameters to keep the permutations simpler
854 // these can NOT degrade! only use for simple stuff
855 enum
856 {
857         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
858         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
859         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
861         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
862         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
863         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
864         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
865         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
866         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
867         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
868         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
869         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
870 };
871 #define SHADERSTATICPARMS_COUNT 13
872
873 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
874 static int shaderstaticparms_count = 0;
875
876 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
877 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
878
879 extern qboolean r_shadow_shadowmapsampler;
880 extern int r_shadow_shadowmappcf;
881 qboolean R_CompileShader_CheckStaticParms(void)
882 {
883         static int r_compileshader_staticparms_save[1];
884         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
885         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
886
887         // detect all
888         if (r_glsl_saturation_redcompensate.integer)
889                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
890         if (r_glsl_vertextextureblend_usebothalphas.integer)
891                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
892         if (r_shadow_glossexact.integer)
893                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
894         if (r_glsl_postprocess.integer)
895         {
896                 if (r_glsl_postprocess_uservec1_enable.integer)
897                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
898                 if (r_glsl_postprocess_uservec2_enable.integer)
899                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
900                 if (r_glsl_postprocess_uservec3_enable.integer)
901                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
902                 if (r_glsl_postprocess_uservec4_enable.integer)
903                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
904         }
905         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
906                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
907
908         if (r_shadow_shadowmapsampler)
909                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
910         if (r_shadow_shadowmappcf > 1)
911                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
912         else if (r_shadow_shadowmappcf)
913                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
914         if (r_celshading.integer)
915                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
916         if (r_celoutlines.integer)
917                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
918
919         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
920 }
921
922 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
923         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
924                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
925         else \
926                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
927 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
928 {
929         shaderstaticparms_count = 0;
930
931         // emit all
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
936         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
937         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
938         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
939         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
940         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
941         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
942         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
943         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
944         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
945 }
946
947 /// information about each possible shader permutation
948 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
949 /// currently selected permutation
950 r_glsl_permutation_t *r_glsl_permutation;
951 /// storage for permutations linked in the hash table
952 memexpandablearray_t r_glsl_permutationarray;
953
954 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
955 {
956         //unsigned int hashdepth = 0;
957         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
958         r_glsl_permutation_t *p;
959         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
960         {
961                 if (p->mode == mode && p->permutation == permutation)
962                 {
963                         //if (hashdepth > 10)
964                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
965                         return p;
966                 }
967                 //hashdepth++;
968         }
969         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
970         p->mode = mode;
971         p->permutation = permutation;
972         p->hashnext = r_glsl_permutationhash[mode][hashindex];
973         r_glsl_permutationhash[mode][hashindex] = p;
974         //if (hashdepth > 10)
975         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
976         return p;
977 }
978
979 static char *R_ShaderStrCat(const char **strings)
980 {
981         char *string, *s;
982         const char **p = strings;
983         const char *t;
984         size_t len = 0;
985         for (p = strings;(t = *p);p++)
986                 len += strlen(t);
987         len++;
988         s = string = (char *)Mem_Alloc(r_main_mempool, len);
989         len = 0;
990         for (p = strings;(t = *p);p++)
991         {
992                 len = strlen(t);
993                 memcpy(s, t, len);
994                 s += len;
995         }
996         *s = 0;
997         return string;
998 }
999
1000 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1001 {
1002         char *shaderstring;
1003         if (!filename || !filename[0])
1004                 return NULL;
1005         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1006         if (!strcmp(filename, "glsl/default.glsl"))
1007         {
1008                 if (builtinonly)
1009                         return R_ShaderStrCat(builtinshaderstrings);
1010                 if (!glslshaderstring)
1011                 {
1012                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1013                         if (glslshaderstring)
1014                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1015                         else
1016                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1017                 }
1018                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1019                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1020                 return shaderstring;
1021         }
1022         if (!strcmp(filename, "hlsl/default.hlsl"))
1023         {
1024                 if (builtinonly)
1025                         return R_ShaderStrCat(builtinhlslshaderstrings);
1026                 if (!hlslshaderstring)
1027                 {
1028                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1029                         if (hlslshaderstring)
1030                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1031                         else
1032                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1033                 }
1034                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1035                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1036                 return shaderstring;
1037         }
1038         // we don't have builtin strings for any other files
1039         if (builtinonly)
1040                 return NULL;
1041         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1042         if (shaderstring)
1043         {
1044                 if (printfromdisknotice)
1045                         Con_DPrintf("from disk %s... ", filename);
1046                 return shaderstring;
1047         }
1048         return shaderstring;
1049 }
1050
1051 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1052 {
1053         int i;
1054         int sampler;
1055         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1056         char *sourcestring;
1057         char permutationname[256];
1058         int vertstrings_count = 0;
1059         int geomstrings_count = 0;
1060         int fragstrings_count = 0;
1061         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1062         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1063         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1064
1065         if (p->compiled)
1066                 return;
1067         p->compiled = true;
1068         p->program = 0;
1069
1070         permutationname[0] = 0;
1071         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1072
1073         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1074
1075         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1076         if(vid.support.gl20shaders130)
1077         {
1078                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1079                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1080                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1081                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1082                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1083                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1084         }
1085
1086         // the first pretext is which type of shader to compile as
1087         // (later these will all be bound together as a program object)
1088         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1089         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1090         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1091
1092         // the second pretext is the mode (for example a light source)
1093         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1094         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1095         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1096         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1097
1098         // now add all the permutation pretexts
1099         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1100         {
1101                 if (permutation & (1<<i))
1102                 {
1103                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1104                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1105                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1106                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1107                 }
1108                 else
1109                 {
1110                         // keep line numbers correct
1111                         vertstrings_list[vertstrings_count++] = "\n";
1112                         geomstrings_list[geomstrings_count++] = "\n";
1113                         fragstrings_list[fragstrings_count++] = "\n";
1114                 }
1115         }
1116
1117         // add static parms
1118         R_CompileShader_AddStaticParms(mode, permutation);
1119         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1120         vertstrings_count += shaderstaticparms_count;
1121         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1122         geomstrings_count += shaderstaticparms_count;
1123         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1124         fragstrings_count += shaderstaticparms_count;
1125
1126         // now append the shader text itself
1127         vertstrings_list[vertstrings_count++] = sourcestring;
1128         geomstrings_list[geomstrings_count++] = sourcestring;
1129         fragstrings_list[fragstrings_count++] = sourcestring;
1130
1131         // compile the shader program
1132         if (vertstrings_count + geomstrings_count + fragstrings_count)
1133                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1134         if (p->program)
1135         {
1136                 CHECKGLERROR
1137                 qglUseProgram(p->program);CHECKGLERROR
1138                 // look up all the uniform variable names we care about, so we don't
1139                 // have to look them up every time we set them
1140
1141                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1142                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1143                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1144                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1145                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1146                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1147                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1148                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1149                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1150                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1151                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1152                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1153                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1154                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1155                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1156                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1157                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1158                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1159                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1160                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1161                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1162                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1163                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1164                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1165                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1166                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1167                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1168                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1169                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1170                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1171                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1172                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1173                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1174                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1175                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1176                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1177                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1178                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1179                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1180                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1181                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1182                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1183                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1184                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1185                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1186                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1187                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1188                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1189                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1190                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1191                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1192                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1193                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1194                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1195                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1196                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1197                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1198                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1199                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1200                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1201                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1202                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1203                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1204                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1205                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1206                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1207                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1208                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1209                 p->loc_Skeletal_Transform12       = qglGetUniformLocation(p->program, "Skeletal_Transform12");
1210                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1211                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1212                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1213                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1214                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1215                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1216                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1217                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1218                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1219                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1220                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1221                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1222                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1223                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1224                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1225                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1226                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1227                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1228                 // initialize the samplers to refer to the texture units we use
1229                 p->tex_Texture_First = -1;
1230                 p->tex_Texture_Second = -1;
1231                 p->tex_Texture_GammaRamps = -1;
1232                 p->tex_Texture_Normal = -1;
1233                 p->tex_Texture_Color = -1;
1234                 p->tex_Texture_Gloss = -1;
1235                 p->tex_Texture_Glow = -1;
1236                 p->tex_Texture_SecondaryNormal = -1;
1237                 p->tex_Texture_SecondaryColor = -1;
1238                 p->tex_Texture_SecondaryGloss = -1;
1239                 p->tex_Texture_SecondaryGlow = -1;
1240                 p->tex_Texture_Pants = -1;
1241                 p->tex_Texture_Shirt = -1;
1242                 p->tex_Texture_FogHeightTexture = -1;
1243                 p->tex_Texture_FogMask = -1;
1244                 p->tex_Texture_Lightmap = -1;
1245                 p->tex_Texture_Deluxemap = -1;
1246                 p->tex_Texture_Attenuation = -1;
1247                 p->tex_Texture_Cube = -1;
1248                 p->tex_Texture_Refraction = -1;
1249                 p->tex_Texture_Reflection = -1;
1250                 p->tex_Texture_ShadowMap2D = -1;
1251                 p->tex_Texture_CubeProjection = -1;
1252                 p->tex_Texture_ScreenNormalMap = -1;
1253                 p->tex_Texture_ScreenDiffuse = -1;
1254                 p->tex_Texture_ScreenSpecular = -1;
1255                 p->tex_Texture_ReflectMask = -1;
1256                 p->tex_Texture_ReflectCube = -1;
1257                 p->tex_Texture_BounceGrid = -1;
1258                 sampler = 0;
1259                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1260                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1261                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1262                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1263                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1264                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1265                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1266                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1267                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1268                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1269                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1270                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1271                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1272                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1273                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1274                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1275                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1276                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1277                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1278                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1279                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1280                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1281                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1282                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1283                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1284                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1285                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1286                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1287                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1288                 CHECKGLERROR
1289                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1290         }
1291         else
1292                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1293
1294         // free the strings
1295         if (sourcestring)
1296                 Mem_Free(sourcestring);
1297 }
1298
1299 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1300 {
1301         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1302         if (r_glsl_permutation != perm)
1303         {
1304                 r_glsl_permutation = perm;
1305                 if (!r_glsl_permutation->program)
1306                 {
1307                         if (!r_glsl_permutation->compiled)
1308                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1309                         if (!r_glsl_permutation->program)
1310                         {
1311                                 // remove features until we find a valid permutation
1312                                 int i;
1313                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1314                                 {
1315                                         // reduce i more quickly whenever it would not remove any bits
1316                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1317                                         if (!(permutation & j))
1318                                                 continue;
1319                                         permutation -= j;
1320                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1321                                         if (!r_glsl_permutation->compiled)
1322                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1323                                         if (r_glsl_permutation->program)
1324                                                 break;
1325                                 }
1326                                 if (i >= SHADERPERMUTATION_COUNT)
1327                                 {
1328                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1329                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1330                                         qglUseProgram(0);CHECKGLERROR
1331                                         return; // no bit left to clear, entire mode is broken
1332                                 }
1333                         }
1334                 }
1335                 CHECKGLERROR
1336                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1337         }
1338         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1339         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1340         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1341 }
1342
1343 #ifdef SUPPORTD3D
1344
1345 #ifdef SUPPORTD3D
1346 #include <d3d9.h>
1347 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1348 extern D3DCAPS9 vid_d3d9caps;
1349 #endif
1350
1351 struct r_hlsl_permutation_s;
1352 typedef struct r_hlsl_permutation_s
1353 {
1354         /// hash lookup data
1355         struct r_hlsl_permutation_s *hashnext;
1356         unsigned int mode;
1357         unsigned int permutation;
1358
1359         /// indicates if we have tried compiling this permutation already
1360         qboolean compiled;
1361         /// NULL if compilation failed
1362         IDirect3DVertexShader9 *vertexshader;
1363         IDirect3DPixelShader9 *pixelshader;
1364 }
1365 r_hlsl_permutation_t;
1366
1367 typedef enum D3DVSREGISTER_e
1368 {
1369         D3DVSREGISTER_TexMatrix = 0, // float4x4
1370         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1371         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1372         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1373         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1374         D3DVSREGISTER_ModelToLight = 20, // float4x4
1375         D3DVSREGISTER_EyePosition = 24,
1376         D3DVSREGISTER_FogPlane = 25,
1377         D3DVSREGISTER_LightDir = 26,
1378         D3DVSREGISTER_LightPosition = 27,
1379 }
1380 D3DVSREGISTER_t;
1381
1382 typedef enum D3DPSREGISTER_e
1383 {
1384         D3DPSREGISTER_Alpha = 0,
1385         D3DPSREGISTER_BloomBlur_Parameters = 1,
1386         D3DPSREGISTER_ClientTime = 2,
1387         D3DPSREGISTER_Color_Ambient = 3,
1388         D3DPSREGISTER_Color_Diffuse = 4,
1389         D3DPSREGISTER_Color_Specular = 5,
1390         D3DPSREGISTER_Color_Glow = 6,
1391         D3DPSREGISTER_Color_Pants = 7,
1392         D3DPSREGISTER_Color_Shirt = 8,
1393         D3DPSREGISTER_DeferredColor_Ambient = 9,
1394         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1395         D3DPSREGISTER_DeferredColor_Specular = 11,
1396         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1397         D3DPSREGISTER_DeferredMod_Specular = 13,
1398         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1399         D3DPSREGISTER_EyePosition = 15, // unused
1400         D3DPSREGISTER_FogColor = 16,
1401         D3DPSREGISTER_FogHeightFade = 17,
1402         D3DPSREGISTER_FogPlane = 18,
1403         D3DPSREGISTER_FogPlaneViewDist = 19,
1404         D3DPSREGISTER_FogRangeRecip = 20,
1405         D3DPSREGISTER_LightColor = 21,
1406         D3DPSREGISTER_LightDir = 22, // unused
1407         D3DPSREGISTER_LightPosition = 23,
1408         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1409         D3DPSREGISTER_PixelSize = 25,
1410         D3DPSREGISTER_ReflectColor = 26,
1411         D3DPSREGISTER_ReflectFactor = 27,
1412         D3DPSREGISTER_ReflectOffset = 28,
1413         D3DPSREGISTER_RefractColor = 29,
1414         D3DPSREGISTER_Saturation = 30,
1415         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1416         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1417         D3DPSREGISTER_ScreenToDepth = 33,
1418         D3DPSREGISTER_ShadowMap_Parameters = 34,
1419         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1420         D3DPSREGISTER_SpecularPower = 36,
1421         D3DPSREGISTER_UserVec1 = 37,
1422         D3DPSREGISTER_UserVec2 = 38,
1423         D3DPSREGISTER_UserVec3 = 39,
1424         D3DPSREGISTER_UserVec4 = 40,
1425         D3DPSREGISTER_ViewTintColor = 41,
1426         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1427         D3DPSREGISTER_BloomColorSubtract = 43,
1428         D3DPSREGISTER_ViewToLight = 44, // float4x4
1429         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1430         D3DPSREGISTER_NormalmapScrollBlend = 52,
1431         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1432         D3DPSREGISTER_OffsetMapping_Bias = 54,
1433         // next at 54
1434 }
1435 D3DPSREGISTER_t;
1436
1437 /// information about each possible shader permutation
1438 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1439 /// currently selected permutation
1440 r_hlsl_permutation_t *r_hlsl_permutation;
1441 /// storage for permutations linked in the hash table
1442 memexpandablearray_t r_hlsl_permutationarray;
1443
1444 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1445 {
1446         //unsigned int hashdepth = 0;
1447         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1448         r_hlsl_permutation_t *p;
1449         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1450         {
1451                 if (p->mode == mode && p->permutation == permutation)
1452                 {
1453                         //if (hashdepth > 10)
1454                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1455                         return p;
1456                 }
1457                 //hashdepth++;
1458         }
1459         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1460         p->mode = mode;
1461         p->permutation = permutation;
1462         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1463         r_hlsl_permutationhash[mode][hashindex] = p;
1464         //if (hashdepth > 10)
1465         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1466         return p;
1467 }
1468
1469 #include <d3dx9.h>
1470 //#include <d3dx9shader.h>
1471 //#include <d3dx9mesh.h>
1472
1473 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1474 {
1475         DWORD *vsbin = NULL;
1476         DWORD *psbin = NULL;
1477         fs_offset_t vsbinsize;
1478         fs_offset_t psbinsize;
1479 //      IDirect3DVertexShader9 *vs = NULL;
1480 //      IDirect3DPixelShader9 *ps = NULL;
1481         ID3DXBuffer *vslog = NULL;
1482         ID3DXBuffer *vsbuffer = NULL;
1483         ID3DXConstantTable *vsconstanttable = NULL;
1484         ID3DXBuffer *pslog = NULL;
1485         ID3DXBuffer *psbuffer = NULL;
1486         ID3DXConstantTable *psconstanttable = NULL;
1487         int vsresult = 0;
1488         int psresult = 0;
1489         char temp[MAX_INPUTLINE];
1490         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1491         char vabuf[1024];
1492         qboolean debugshader = gl_paranoid.integer != 0;
1493         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1494         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1495         if (!debugshader)
1496         {
1497                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1498                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1499         }
1500         if ((!vsbin && vertstring) || (!psbin && fragstring))
1501         {
1502                 const char* dllnames_d3dx9 [] =
1503                 {
1504                         "d3dx9_43.dll",
1505                         "d3dx9_42.dll",
1506                         "d3dx9_41.dll",
1507                         "d3dx9_40.dll",
1508                         "d3dx9_39.dll",
1509                         "d3dx9_38.dll",
1510                         "d3dx9_37.dll",
1511                         "d3dx9_36.dll",
1512                         "d3dx9_35.dll",
1513                         "d3dx9_34.dll",
1514                         "d3dx9_33.dll",
1515                         "d3dx9_32.dll",
1516                         "d3dx9_31.dll",
1517                         "d3dx9_30.dll",
1518                         "d3dx9_29.dll",
1519                         "d3dx9_28.dll",
1520                         "d3dx9_27.dll",
1521                         "d3dx9_26.dll",
1522                         "d3dx9_25.dll",
1523                         "d3dx9_24.dll",
1524                         NULL
1525                 };
1526                 dllhandle_t d3dx9_dll = NULL;
1527                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1528                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1529                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1530                 dllfunction_t d3dx9_dllfuncs[] =
1531                 {
1532                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1533                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1534                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1535                         {NULL, NULL}
1536                 };
1537                 // 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...
1538 #ifndef ID3DXBuffer_GetBufferPointer
1539 #if !defined(__cplusplus) || defined(CINTERFACE)
1540 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1541 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1542 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1543 #else
1544 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1545 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1546 #define ID3DXBuffer_Release(p)            (p)->Release()
1547 #endif
1548 #endif
1549                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1550                 {
1551                         DWORD shaderflags = 0;
1552                         if (debugshader)
1553                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1554                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1555                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1556                         if (vertstring && vertstring[0])
1557                         {
1558                                 if (debugshader)
1559                                 {
1560                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1561                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1562                                 }
1563                                 else
1564                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1565                                 if (vsbuffer)
1566                                 {
1567                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1568                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1569                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1570                                         ID3DXBuffer_Release(vsbuffer);
1571                                 }
1572                                 if (vslog)
1573                                 {
1574                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1575                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1576                                         ID3DXBuffer_Release(vslog);
1577                                 }
1578                         }
1579                         if (fragstring && fragstring[0])
1580                         {
1581                                 if (debugshader)
1582                                 {
1583                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1584                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1585                                 }
1586                                 else
1587                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1588                                 if (psbuffer)
1589                                 {
1590                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1591                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1592                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1593                                         ID3DXBuffer_Release(psbuffer);
1594                                 }
1595                                 if (pslog)
1596                                 {
1597                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1598                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1599                                         ID3DXBuffer_Release(pslog);
1600                                 }
1601                         }
1602                         Sys_UnloadLibrary(&d3dx9_dll);
1603                 }
1604                 else
1605                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1606         }
1607         if (vsbin && psbin)
1608         {
1609                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1610                 if (FAILED(vsresult))
1611                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1612                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1613                 if (FAILED(psresult))
1614                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1615         }
1616         // free the shader data
1617         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1618         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1619 }
1620
1621 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1622 {
1623         int i;
1624         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1625         int vertstring_length = 0;
1626         int geomstring_length = 0;
1627         int fragstring_length = 0;
1628         char *t;
1629         char *sourcestring;
1630         char *vertstring, *geomstring, *fragstring;
1631         char permutationname[256];
1632         char cachename[256];
1633         int vertstrings_count = 0;
1634         int geomstrings_count = 0;
1635         int fragstrings_count = 0;
1636         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1637         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1638         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1639
1640         if (p->compiled)
1641                 return;
1642         p->compiled = true;
1643         p->vertexshader = NULL;
1644         p->pixelshader = NULL;
1645
1646         permutationname[0] = 0;
1647         cachename[0] = 0;
1648         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1649
1650         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1651         strlcat(cachename, "hlsl/", sizeof(cachename));
1652
1653         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1654         vertstrings_count = 0;
1655         geomstrings_count = 0;
1656         fragstrings_count = 0;
1657         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1658         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1659         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1660
1661         // the first pretext is which type of shader to compile as
1662         // (later these will all be bound together as a program object)
1663         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1664         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1665         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1666
1667         // the second pretext is the mode (for example a light source)
1668         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1669         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1670         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1671         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1672         strlcat(cachename, modeinfo->name, sizeof(cachename));
1673
1674         // now add all the permutation pretexts
1675         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1676         {
1677                 if (permutation & (1<<i))
1678                 {
1679                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1680                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1681                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1682                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1683                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1684                 }
1685                 else
1686                 {
1687                         // keep line numbers correct
1688                         vertstrings_list[vertstrings_count++] = "\n";
1689                         geomstrings_list[geomstrings_count++] = "\n";
1690                         fragstrings_list[fragstrings_count++] = "\n";
1691                 }
1692         }
1693
1694         // add static parms
1695         R_CompileShader_AddStaticParms(mode, permutation);
1696         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1697         vertstrings_count += shaderstaticparms_count;
1698         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1699         geomstrings_count += shaderstaticparms_count;
1700         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1701         fragstrings_count += shaderstaticparms_count;
1702
1703         // replace spaces in the cachename with _ characters
1704         for (i = 0;cachename[i];i++)
1705                 if (cachename[i] == ' ')
1706                         cachename[i] = '_';
1707
1708         // now append the shader text itself
1709         vertstrings_list[vertstrings_count++] = sourcestring;
1710         geomstrings_list[geomstrings_count++] = sourcestring;
1711         fragstrings_list[fragstrings_count++] = sourcestring;
1712
1713         vertstring_length = 0;
1714         for (i = 0;i < vertstrings_count;i++)
1715                 vertstring_length += strlen(vertstrings_list[i]);
1716         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1717         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1718                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1719
1720         geomstring_length = 0;
1721         for (i = 0;i < geomstrings_count;i++)
1722                 geomstring_length += strlen(geomstrings_list[i]);
1723         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1724         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1725                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1726
1727         fragstring_length = 0;
1728         for (i = 0;i < fragstrings_count;i++)
1729                 fragstring_length += strlen(fragstrings_list[i]);
1730         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1731         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1732                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1733
1734         // try to load the cached shader, or generate one
1735         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1736
1737         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1738                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1739         else
1740                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1741
1742         // free the strings
1743         if (vertstring)
1744                 Mem_Free(vertstring);
1745         if (geomstring)
1746                 Mem_Free(geomstring);
1747         if (fragstring)
1748                 Mem_Free(fragstring);
1749         if (sourcestring)
1750                 Mem_Free(sourcestring);
1751 }
1752
1753 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1754 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1755 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);}
1756 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);}
1757 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);}
1758 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);}
1759
1760 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1761 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1762 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);}
1763 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);}
1764 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);}
1765 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);}
1766
1767 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1768 {
1769         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1770         if (r_hlsl_permutation != perm)
1771         {
1772                 r_hlsl_permutation = perm;
1773                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1774                 {
1775                         if (!r_hlsl_permutation->compiled)
1776                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1777                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1778                         {
1779                                 // remove features until we find a valid permutation
1780                                 int i;
1781                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1782                                 {
1783                                         // reduce i more quickly whenever it would not remove any bits
1784                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1785                                         if (!(permutation & j))
1786                                                 continue;
1787                                         permutation -= j;
1788                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1789                                         if (!r_hlsl_permutation->compiled)
1790                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1791                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1792                                                 break;
1793                                 }
1794                                 if (i >= SHADERPERMUTATION_COUNT)
1795                                 {
1796                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1797                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1798                                         return; // no bit left to clear, entire mode is broken
1799                                 }
1800                         }
1801                 }
1802                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1803                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1804         }
1805         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1806         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1807         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1808 }
1809 #endif
1810
1811 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1812 {
1813         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1814         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1815         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1816         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1817 }
1818
1819 void R_GLSL_Restart_f(void)
1820 {
1821         unsigned int i, limit;
1822         if (glslshaderstring)
1823                 Mem_Free(glslshaderstring);
1824         glslshaderstring = NULL;
1825         if (hlslshaderstring)
1826                 Mem_Free(hlslshaderstring);
1827         hlslshaderstring = NULL;
1828         switch(vid.renderpath)
1829         {
1830         case RENDERPATH_D3D9:
1831 #ifdef SUPPORTD3D
1832                 {
1833                         r_hlsl_permutation_t *p;
1834                         r_hlsl_permutation = NULL;
1835                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1836                         for (i = 0;i < limit;i++)
1837                         {
1838                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1839                                 {
1840                                         if (p->vertexshader)
1841                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1842                                         if (p->pixelshader)
1843                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1844                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1845                                 }
1846                         }
1847                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1848                 }
1849 #endif
1850                 break;
1851         case RENDERPATH_D3D10:
1852                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1853                 break;
1854         case RENDERPATH_D3D11:
1855                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1856                 break;
1857         case RENDERPATH_GL20:
1858         case RENDERPATH_GLES2:
1859                 {
1860                         r_glsl_permutation_t *p;
1861                         r_glsl_permutation = NULL;
1862                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1863                         for (i = 0;i < limit;i++)
1864                         {
1865                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1866                                 {
1867                                         GL_Backend_FreeProgram(p->program);
1868                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1869                                 }
1870                         }
1871                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1872                 }
1873                 break;
1874         case RENDERPATH_GL11:
1875         case RENDERPATH_GL13:
1876         case RENDERPATH_GLES1:
1877                 break;
1878         case RENDERPATH_SOFT:
1879                 break;
1880         }
1881 }
1882
1883 static void R_GLSL_DumpShader_f(void)
1884 {
1885         int i, language, mode, dupe;
1886         char *text;
1887         shadermodeinfo_t *modeinfo;
1888         qfile_t *file;
1889
1890         for (language = 0;language < 2;language++)
1891         {
1892                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1893                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1894                 {
1895                         // don't dump the same file multiple times (most or all shaders come from the same file)
1896                         for (dupe = mode - 1;dupe >= 0;dupe--)
1897                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1898                                         break;
1899                         if (dupe >= 0)
1900                                 continue;
1901                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1902                         if (!text)
1903                                 continue;
1904                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1905                         if (file)
1906                         {
1907                                 FS_Print(file, "/* The engine may define the following macros:\n");
1908                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1909                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1910                                         FS_Print(file, modeinfo[i].pretext);
1911                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1912                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1913                                 FS_Print(file, "*/\n");
1914                                 FS_Print(file, text);
1915                                 FS_Close(file);
1916                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1917                         }
1918                         else
1919                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1920                         Mem_Free(text);
1921                 }
1922         }
1923 }
1924
1925 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1926 {
1927         unsigned int permutation = 0;
1928         if (r_trippy.integer && !notrippy)
1929                 permutation |= SHADERPERMUTATION_TRIPPY;
1930         permutation |= SHADERPERMUTATION_VIEWTINT;
1931         if (first)
1932                 permutation |= SHADERPERMUTATION_DIFFUSE;
1933         if (second)
1934                 permutation |= SHADERPERMUTATION_SPECULAR;
1935         if (texturemode == GL_MODULATE)
1936                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1937         else if (texturemode == GL_ADD)
1938                 permutation |= SHADERPERMUTATION_GLOW;
1939         else if (texturemode == GL_DECAL)
1940                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1941         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1942                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1943         if (suppresstexalpha)
1944                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1945         if (!second)
1946                 texturemode = GL_MODULATE;
1947         if (vid.allowalphatocoverage)
1948                 GL_AlphaToCoverage(false);
1949         switch (vid.renderpath)
1950         {
1951         case RENDERPATH_D3D9:
1952 #ifdef SUPPORTD3D
1953                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1954                 R_Mesh_TexBind(GL20TU_FIRST , first );
1955                 R_Mesh_TexBind(GL20TU_SECOND, second);
1956                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1957                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1958 #endif
1959                 break;
1960         case RENDERPATH_D3D10:
1961                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1962                 break;
1963         case RENDERPATH_D3D11:
1964                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1965                 break;
1966         case RENDERPATH_GL20:
1967         case RENDERPATH_GLES2:
1968                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1969                 if (r_glsl_permutation->tex_Texture_First >= 0)
1970                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1971                 if (r_glsl_permutation->tex_Texture_Second >= 0)
1972                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1973                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1974                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1975                 break;
1976         case RENDERPATH_GL13:
1977         case RENDERPATH_GLES1:
1978                 R_Mesh_TexBind(0, first );
1979                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1980                 R_Mesh_TexMatrix(0, NULL);
1981                 R_Mesh_TexBind(1, second);
1982                 if (second)
1983                 {
1984                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1985                         R_Mesh_TexMatrix(1, NULL);
1986                 }
1987                 break;
1988         case RENDERPATH_GL11:
1989                 R_Mesh_TexBind(0, first );
1990                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1991                 R_Mesh_TexMatrix(0, NULL);
1992                 break;
1993         case RENDERPATH_SOFT:
1994                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1995                 R_Mesh_TexBind(GL20TU_FIRST , first );
1996                 R_Mesh_TexBind(GL20TU_SECOND, second);
1997                 break;
1998         }
1999 }
2000
2001 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2002 {
2003         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2004 }
2005
2006 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2007 {
2008         unsigned int permutation = 0;
2009         if (r_trippy.integer && !notrippy)
2010                 permutation |= SHADERPERMUTATION_TRIPPY;
2011         if (depthrgb)
2012                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2013         if (skeletal)
2014                 permutation |= SHADERPERMUTATION_SKELETAL;
2015
2016         if (vid.allowalphatocoverage)
2017                 GL_AlphaToCoverage(false);
2018         switch (vid.renderpath)
2019         {
2020         case RENDERPATH_D3D9:
2021 #ifdef SUPPORTD3D
2022                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2023 #endif
2024                 break;
2025         case RENDERPATH_D3D10:
2026                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2027                 break;
2028         case RENDERPATH_D3D11:
2029                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2030                 break;
2031         case RENDERPATH_GL20:
2032         case RENDERPATH_GLES2:
2033                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2034                 break;
2035         case RENDERPATH_GL13:
2036         case RENDERPATH_GLES1:
2037                 R_Mesh_TexBind(0, 0);
2038                 R_Mesh_TexBind(1, 0);
2039                 break;
2040         case RENDERPATH_GL11:
2041                 R_Mesh_TexBind(0, 0);
2042                 break;
2043         case RENDERPATH_SOFT:
2044                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2045                 break;
2046         }
2047 }
2048
2049 extern qboolean r_shadow_usingdeferredprepass;
2050 extern rtexture_t *r_shadow_attenuationgradienttexture;
2051 extern rtexture_t *r_shadow_attenuation2dtexture;
2052 extern rtexture_t *r_shadow_attenuation3dtexture;
2053 extern qboolean r_shadow_usingshadowmap2d;
2054 extern qboolean r_shadow_usingshadowmaportho;
2055 extern float r_shadow_shadowmap_texturescale[2];
2056 extern float r_shadow_shadowmap_parameters[4];
2057 extern qboolean r_shadow_shadowmapvsdct;
2058 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2059 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2060 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2061 extern matrix4x4_t r_shadow_shadowmapmatrix;
2062 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2063 extern int r_shadow_prepass_width;
2064 extern int r_shadow_prepass_height;
2065 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2066 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2067 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2068 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2069
2070 #define BLENDFUNC_ALLOWS_COLORMOD      1
2071 #define BLENDFUNC_ALLOWS_FOG           2
2072 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2073 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2074 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2075 static int R_BlendFuncFlags(int src, int dst)
2076 {
2077         int r = 0;
2078
2079         // a blendfunc allows colormod if:
2080         // a) it can never keep the destination pixel invariant, or
2081         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2082         // this is to prevent unintended side effects from colormod
2083
2084         // a blendfunc allows fog if:
2085         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2086         // this is to prevent unintended side effects from fog
2087
2088         // these checks are the output of fogeval.pl
2089
2090         r |= BLENDFUNC_ALLOWS_COLORMOD;
2091         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2092         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2093         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2094         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2095         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2096         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2097         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2099         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2100         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2101         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2102         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2103         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2104         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2105         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2106         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2107         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2108         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2109         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2110         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2111         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2112
2113         return r;
2114 }
2115
2116 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)
2117 {
2118         // select a permutation of the lighting shader appropriate to this
2119         // combination of texture, entity, light source, and fogging, only use the
2120         // minimum features necessary to avoid wasting rendering time in the
2121         // fragment shader on features that are not being used
2122         unsigned int permutation = 0;
2123         unsigned int mode = 0;
2124         int blendfuncflags;
2125         static float dummy_colormod[3] = {1, 1, 1};
2126         float *colormod = rsurface.colormod;
2127         float m16f[16];
2128         matrix4x4_t tempmatrix;
2129         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2130         if (r_trippy.integer && !notrippy)
2131                 permutation |= SHADERPERMUTATION_TRIPPY;
2132         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2133                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2134         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2135                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2136         if (rsurfacepass == RSURFPASS_BACKGROUND)
2137         {
2138                 // distorted background
2139                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2140                 {
2141                         mode = SHADERMODE_WATER;
2142                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2143                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2144                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2145                         {
2146                                 // this is the right thing to do for wateralpha
2147                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2148                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2149                         }
2150                         else
2151                         {
2152                                 // this is the right thing to do for entity alpha
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                 }
2157                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2158                 {
2159                         mode = SHADERMODE_REFRACTION;
2160                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2161                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2162                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2163                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2164                 }
2165                 else
2166                 {
2167                         mode = SHADERMODE_GENERIC;
2168                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2169                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2170                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2171                 }
2172                 if (vid.allowalphatocoverage)
2173                         GL_AlphaToCoverage(false);
2174         }
2175         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2176         {
2177                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2178                 {
2179                         switch(rsurface.texture->offsetmapping)
2180                         {
2181                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2182                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2183                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2184                         case OFFSETMAPPING_OFF: break;
2185                         }
2186                 }
2187                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2188                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2189                 // normalmap (deferred prepass), may use alpha test on diffuse
2190                 mode = SHADERMODE_DEFERREDGEOMETRY;
2191                 GL_BlendFunc(GL_ONE, GL_ZERO);
2192                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2193                 if (vid.allowalphatocoverage)
2194                         GL_AlphaToCoverage(false);
2195         }
2196         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2197         {
2198                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2199                 {
2200                         switch(rsurface.texture->offsetmapping)
2201                         {
2202                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2203                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2204                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2205                         case OFFSETMAPPING_OFF: break;
2206                         }
2207                 }
2208                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2209                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2210                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2211                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2212                 // light source
2213                 mode = SHADERMODE_LIGHTSOURCE;
2214                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2215                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2216                 if (diffusescale > 0)
2217                         permutation |= SHADERPERMUTATION_DIFFUSE;
2218                 if (specularscale > 0)
2219                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2220                 if (r_refdef.fogenabled)
2221                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2222                 if (rsurface.texture->colormapping)
2223                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2224                 if (r_shadow_usingshadowmap2d)
2225                 {
2226                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2227                         if(r_shadow_shadowmapvsdct)
2228                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2229
2230                         if (r_shadow_shadowmap2ddepthbuffer)
2231                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2232                 }
2233                 if (rsurface.texture->reflectmasktexture)
2234                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2235                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2236                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2237                 if (vid.allowalphatocoverage)
2238                         GL_AlphaToCoverage(false);
2239         }
2240         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2241         {
2242                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2243                 {
2244                         switch(rsurface.texture->offsetmapping)
2245                         {
2246                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2247                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2248                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2249                         case OFFSETMAPPING_OFF: break;
2250                         }
2251                 }
2252                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2253                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2254                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2255                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2256                 // unshaded geometry (fullbright or ambient model lighting)
2257                 mode = SHADERMODE_FLATCOLOR;
2258                 ambientscale = diffusescale = specularscale = 0;
2259                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2260                         permutation |= SHADERPERMUTATION_GLOW;
2261                 if (r_refdef.fogenabled)
2262                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2263                 if (rsurface.texture->colormapping)
2264                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2265                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2266                 {
2267                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2268                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2269
2270                         if (r_shadow_shadowmap2ddepthbuffer)
2271                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2272                 }
2273                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2274                         permutation |= SHADERPERMUTATION_REFLECTION;
2275                 if (rsurface.texture->reflectmasktexture)
2276                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2277                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2278                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2279                 // when using alphatocoverage, we don't need alphakill
2280                 if (vid.allowalphatocoverage)
2281                 {
2282                         if (r_transparent_alphatocoverage.integer)
2283                         {
2284                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2285                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2286                         }
2287                         else
2288                                 GL_AlphaToCoverage(false);
2289                 }
2290         }
2291         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2292         {
2293                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2294                 {
2295                         switch(rsurface.texture->offsetmapping)
2296                         {
2297                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2298                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2299                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2300                         case OFFSETMAPPING_OFF: break;
2301                         }
2302                 }
2303                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2304                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2305                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2306                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2307                 // directional model lighting
2308                 mode = SHADERMODE_LIGHTDIRECTION;
2309                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2310                         permutation |= SHADERPERMUTATION_GLOW;
2311                 permutation |= SHADERPERMUTATION_DIFFUSE;
2312                 if (specularscale > 0)
2313                         permutation |= SHADERPERMUTATION_SPECULAR;
2314                 if (r_refdef.fogenabled)
2315                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2316                 if (rsurface.texture->colormapping)
2317                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2318                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2319                 {
2320                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2321                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2322
2323                         if (r_shadow_shadowmap2ddepthbuffer)
2324                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2325                 }
2326                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2327                         permutation |= SHADERPERMUTATION_REFLECTION;
2328                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2329                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2330                 if (rsurface.texture->reflectmasktexture)
2331                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2332                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2333                 {
2334                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2335                         if (r_shadow_bouncegriddirectional)
2336                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2337                 }
2338                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2339                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2340                 // when using alphatocoverage, we don't need alphakill
2341                 if (vid.allowalphatocoverage)
2342                 {
2343                         if (r_transparent_alphatocoverage.integer)
2344                         {
2345                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2346                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2347                         }
2348                         else
2349                                 GL_AlphaToCoverage(false);
2350                 }
2351         }
2352         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2353         {
2354                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2355                 {
2356                         switch(rsurface.texture->offsetmapping)
2357                         {
2358                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2359                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2360                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2361                         case OFFSETMAPPING_OFF: break;
2362                         }
2363                 }
2364                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2365                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2366                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2367                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2368                 // ambient model lighting
2369                 mode = SHADERMODE_LIGHTDIRECTION;
2370                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2371                         permutation |= SHADERPERMUTATION_GLOW;
2372                 if (r_refdef.fogenabled)
2373                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2374                 if (rsurface.texture->colormapping)
2375                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2376                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2377                 {
2378                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2379                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2380
2381                         if (r_shadow_shadowmap2ddepthbuffer)
2382                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2383                 }
2384                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2385                         permutation |= SHADERPERMUTATION_REFLECTION;
2386                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2387                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2388                 if (rsurface.texture->reflectmasktexture)
2389                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2390                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2391                 {
2392                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2393                         if (r_shadow_bouncegriddirectional)
2394                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2395                 }
2396                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2397                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2398                 // when using alphatocoverage, we don't need alphakill
2399                 if (vid.allowalphatocoverage)
2400                 {
2401                         if (r_transparent_alphatocoverage.integer)
2402                         {
2403                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2404                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2405                         }
2406                         else
2407                                 GL_AlphaToCoverage(false);
2408                 }
2409         }
2410         else
2411         {
2412                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2413                 {
2414                         switch(rsurface.texture->offsetmapping)
2415                         {
2416                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2417                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2418                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2419                         case OFFSETMAPPING_OFF: break;
2420                         }
2421                 }
2422                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2423                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2424                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2425                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2426                 // lightmapped wall
2427                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2428                         permutation |= SHADERPERMUTATION_GLOW;
2429                 if (r_refdef.fogenabled)
2430                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2431                 if (rsurface.texture->colormapping)
2432                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2433                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2434                 {
2435                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2436                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2437
2438                         if (r_shadow_shadowmap2ddepthbuffer)
2439                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2440                 }
2441                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2442                         permutation |= SHADERPERMUTATION_REFLECTION;
2443                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2444                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2445                 if (rsurface.texture->reflectmasktexture)
2446                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2447                 if (FAKELIGHT_ENABLED)
2448                 {
2449                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2450                         mode = SHADERMODE_FAKELIGHT;
2451                         permutation |= SHADERPERMUTATION_DIFFUSE;
2452                         if (specularscale > 0)
2453                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2454                 }
2455                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2456                 {
2457                         // deluxemapping (light direction texture)
2458                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2459                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2460                         else
2461                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2462                         permutation |= SHADERPERMUTATION_DIFFUSE;
2463                         if (specularscale > 0)
2464                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2465                 }
2466                 else if (r_glsl_deluxemapping.integer >= 2)
2467                 {
2468                         // fake deluxemapping (uniform light direction in tangentspace)
2469                         if (rsurface.uselightmaptexture)
2470                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2471                         else
2472                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2473                         permutation |= SHADERPERMUTATION_DIFFUSE;
2474                         if (specularscale > 0)
2475                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2476                 }
2477                 else if (rsurface.uselightmaptexture)
2478                 {
2479                         // ordinary lightmapping (q1bsp, q3bsp)
2480                         mode = SHADERMODE_LIGHTMAP;
2481                 }
2482                 else
2483                 {
2484                         // ordinary vertex coloring (q3bsp)
2485                         mode = SHADERMODE_VERTEXCOLOR;
2486                 }
2487                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2488                 {
2489                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2490                         if (r_shadow_bouncegriddirectional)
2491                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2492                 }
2493                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2494                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2495                 // when using alphatocoverage, we don't need alphakill
2496                 if (vid.allowalphatocoverage)
2497                 {
2498                         if (r_transparent_alphatocoverage.integer)
2499                         {
2500                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2501                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2502                         }
2503                         else
2504                                 GL_AlphaToCoverage(false);
2505                 }
2506         }
2507         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2508                 colormod = dummy_colormod;
2509         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2510                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2511         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2512                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2513         switch(vid.renderpath)
2514         {
2515         case RENDERPATH_D3D9:
2516 #ifdef SUPPORTD3D
2517                 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);
2518                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2519                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2520                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2521                 if (mode == SHADERMODE_LIGHTSOURCE)
2522                 {
2523                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2524                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2525                 }
2526                 else
2527                 {
2528                         if (mode == SHADERMODE_LIGHTDIRECTION)
2529                         {
2530                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2531                         }
2532                 }
2533                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2534                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2535                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2536                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2537                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2538
2539                 if (mode == SHADERMODE_LIGHTSOURCE)
2540                 {
2541                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2542                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2543                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2544                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2545                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2546
2547                         // additive passes are only darkened by fog, not tinted
2548                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2549                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2550                 }
2551                 else
2552                 {
2553                         if (mode == SHADERMODE_FLATCOLOR)
2554                         {
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2556                         }
2557                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2558                         {
2559                                 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]);
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2561                                 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);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2565                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2566                         }
2567                         else
2568                         {
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2571                                 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);
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2573                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2574                         }
2575                         // additive passes are only darkened by fog, not tinted
2576                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2578                         else
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2580                         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);
2581                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2582                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2583                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2584                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2585                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2586                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2587                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2588                         if (mode == SHADERMODE_WATER)
2589                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2590                 }
2591                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2592                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2593                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2594                 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));
2595                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2596                 if (rsurface.texture->pantstexture)
2597                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2598                 else
2599                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2600                 if (rsurface.texture->shirttexture)
2601                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2602                 else
2603                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2604                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2605                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2606                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2607                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2608                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2609                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2610                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2611                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2612                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2613                         );
2614                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2615                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2616                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2617                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2618
2619                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2620                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2621                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2622                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2623                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2624                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2625                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2626                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2627                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2628                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2629                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2630                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2631                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2632                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2633                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2634                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2635                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2636                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2637                 {
2638                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2639                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2640                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2641                 }
2642                 else
2643                 {
2644                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2645                 }
2646 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2647                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2648                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2649                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2650                 {
2651                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2652                         if (rsurface.rtlight)
2653                         {
2654                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2655                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2656                         }
2657                 }
2658 #endif
2659                 break;
2660         case RENDERPATH_D3D10:
2661                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2662                 break;
2663         case RENDERPATH_D3D11:
2664                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2665                 break;
2666         case RENDERPATH_GL20:
2667         case RENDERPATH_GLES2:
2668                 if (!vid.useinterleavedarrays)
2669                 {
2670                         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);
2671                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2672                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2673                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2674                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2675                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2676                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2677                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2678                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2679                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2680                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2681                 }
2682                 else
2683                 {
2684                         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);
2685                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2686                 }
2687                 // this has to be after RSurf_PrepareVerticesForBatch
2688                 if (rsurface.batchskeletaltransform3x4)
2689                         permutation |= SHADERPERMUTATION_SKELETAL;
2690                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2691                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2692                 if (mode == SHADERMODE_LIGHTSOURCE)
2693                 {
2694                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2695                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2696                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2697                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2698                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2699                         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);
2700         
2701                         // additive passes are only darkened by fog, not tinted
2702                         if (r_glsl_permutation->loc_FogColor >= 0)
2703                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2704                         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);
2705                 }
2706                 else
2707                 {
2708                         if (mode == SHADERMODE_FLATCOLOR)
2709                         {
2710                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2711                         }
2712                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2713                         {
2714                                 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]);
2715                                 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]);
2716                                 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);
2717                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2718                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2719                                 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]);
2720                                 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]);
2721                         }
2722                         else
2723                         {
2724                                 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]);
2725                                 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]);
2726                                 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);
2727                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2728                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2729                         }
2730                         // additive passes are only darkened by fog, not tinted
2731                         if (r_glsl_permutation->loc_FogColor >= 0)
2732                         {
2733                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2734                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2735                                 else
2736                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2737                         }
2738                         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);
2739                         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]);
2740                         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]);
2741                         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]);
2742                         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]);
2743                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2744                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2745                         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);
2746                         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]);
2747                 }
2748                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2749                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2750                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2751                 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]);
2752                 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]);
2753
2754                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2755                 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));
2756                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2757                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2758                 {
2759                         if (rsurface.texture->pantstexture)
2760                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2761                         else
2762                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2763                 }
2764                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2765                 {
2766                         if (rsurface.texture->shirttexture)
2767                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2768                         else
2769                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2770                 }
2771                 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]);
2772                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2773                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2774                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2775                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2776                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2777                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2778                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2779                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2780                         );
2781                 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);
2782                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2783                 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]);
2784                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2785                 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);}
2786                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2787
2788                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2789                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2790                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2791                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2792                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2793                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2794                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2795                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2796                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2797                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2798                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2799                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2800                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2801                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2802                 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);
2803                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2804                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2805                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2806                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2807                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2808                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2809                 {
2810                         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);
2811                         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);
2812                         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);
2813                 }
2814                 else
2815                 {
2816                         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);
2817                 }
2818                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2819                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2820                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2821                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2822                 {
2823                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2824                         if (rsurface.rtlight)
2825                         {
2826                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2827                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2828                         }
2829                 }
2830                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2831                 if (r_glsl_permutation->loc_Skeletal_Transform12 >= 0 && rsurface.batchskeletalnumtransforms > 0)
2832                         qglUniform4fv(r_glsl_permutation->loc_Skeletal_Transform12, rsurface.batchskeletalnumtransforms*3, rsurface.batchskeletaltransform3x4);
2833                 CHECKGLERROR
2834                 break;
2835         case RENDERPATH_GL11:
2836         case RENDERPATH_GL13:
2837         case RENDERPATH_GLES1:
2838                 break;
2839         case RENDERPATH_SOFT:
2840                 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);
2841                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2842                 R_SetupShader_SetPermutationSoft(mode, permutation);
2843                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2844                 if (mode == SHADERMODE_LIGHTSOURCE)
2845                 {
2846                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2847                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2848                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2849                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2850                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2851                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2852         
2853                         // additive passes are only darkened by fog, not tinted
2854                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2855                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2856                 }
2857                 else
2858                 {
2859                         if (mode == SHADERMODE_FLATCOLOR)
2860                         {
2861                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2862                         }
2863                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2864                         {
2865                                 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]);
2866                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2867                                 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);
2868                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2870                                 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]);
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2872                         }
2873                         else
2874                         {
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2877                                 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);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2880                         }
2881                         // additive passes are only darkened by fog, not tinted
2882                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2883                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2884                         else
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2886                         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);
2887                         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]);
2888                         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]);
2889                         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]);
2890                         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]);
2891                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2892                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2893                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2894                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2895                 }
2896                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2897                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2898                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2899                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2900                 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]);
2901
2902                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2903                 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));
2904                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2905                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2906                 {
2907                         if (rsurface.texture->pantstexture)
2908                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2909                         else
2910                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2911                 }
2912                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2913                 {
2914                         if (rsurface.texture->shirttexture)
2915                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2916                         else
2917                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2918                 }
2919                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2920                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2921                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2922                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2923                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2924                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2925                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2926                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2927                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2928                         );
2929                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2930                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2931                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2932                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2933
2934                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2935                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2936                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2937                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2938                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2939                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2940                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2941                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2942                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2943                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2944                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2945                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2946                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2947                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2948                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2949                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2950                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2951                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2952                 {
2953                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2954                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2955                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2956                 }
2957                 else
2958                 {
2959                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2960                 }
2961 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2962                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2963                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2964                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2965                 {
2966                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2967                         if (rsurface.rtlight)
2968                         {
2969                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2970                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2971                         }
2972                 }
2973                 break;
2974         }
2975 }
2976
2977 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2978 {
2979         // select a permutation of the lighting shader appropriate to this
2980         // combination of texture, entity, light source, and fogging, only use the
2981         // minimum features necessary to avoid wasting rendering time in the
2982         // fragment shader on features that are not being used
2983         unsigned int permutation = 0;
2984         unsigned int mode = 0;
2985         const float *lightcolorbase = rtlight->currentcolor;
2986         float ambientscale = rtlight->ambientscale;
2987         float diffusescale = rtlight->diffusescale;
2988         float specularscale = rtlight->specularscale;
2989         // this is the location of the light in view space
2990         vec3_t viewlightorigin;
2991         // this transforms from view space (camera) to light space (cubemap)
2992         matrix4x4_t viewtolight;
2993         matrix4x4_t lighttoview;
2994         float viewtolight16f[16];
2995         // light source
2996         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2997         if (rtlight->currentcubemap != r_texture_whitecube)
2998                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2999         if (diffusescale > 0)
3000                 permutation |= SHADERPERMUTATION_DIFFUSE;
3001         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3002                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3003         if (r_shadow_usingshadowmap2d)
3004         {
3005                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3006                 if (r_shadow_shadowmapvsdct)
3007                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3008
3009                 if (r_shadow_shadowmap2ddepthbuffer)
3010                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3011         }
3012         if (vid.allowalphatocoverage)
3013                 GL_AlphaToCoverage(false);
3014         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3015         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3016         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3017         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3018         switch(vid.renderpath)
3019         {
3020         case RENDERPATH_D3D9:
3021 #ifdef SUPPORTD3D
3022                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3023                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3024                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3025                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3026                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3027                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3028                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3029                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3030                 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);
3031                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3032                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3033
3034                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3035                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3036                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3037                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3038                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3039 #endif
3040                 break;
3041         case RENDERPATH_D3D10:
3042                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3043                 break;
3044         case RENDERPATH_D3D11:
3045                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3046                 break;
3047         case RENDERPATH_GL20:
3048         case RENDERPATH_GLES2:
3049                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3050                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3051                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3052                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3053                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3054                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3055                 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]);
3056                 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]);
3057                 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);
3058                 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]);
3059                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3060
3061                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3062                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3063                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3064                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3065                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3066                 break;
3067         case RENDERPATH_GL11:
3068         case RENDERPATH_GL13:
3069         case RENDERPATH_GLES1:
3070                 break;
3071         case RENDERPATH_SOFT:
3072                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3073                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3074                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3075                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3076                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3077                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3078                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3079                 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]);
3080                 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);
3081                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3082                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3083
3084                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3085                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3086                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3087                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3088                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3089                 break;
3090         }
3091 }
3092
3093 #define SKINFRAME_HASH 1024
3094
3095 typedef struct
3096 {
3097         int loadsequence; // incremented each level change
3098         memexpandablearray_t array;
3099         skinframe_t *hash[SKINFRAME_HASH];
3100 }
3101 r_skinframe_t;
3102 r_skinframe_t r_skinframe;
3103
3104 void R_SkinFrame_PrepareForPurge(void)
3105 {
3106         r_skinframe.loadsequence++;
3107         // wrap it without hitting zero
3108         if (r_skinframe.loadsequence >= 200)
3109                 r_skinframe.loadsequence = 1;
3110 }
3111
3112 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3113 {
3114         if (!skinframe)
3115                 return;
3116         // mark the skinframe as used for the purging code
3117         skinframe->loadsequence = r_skinframe.loadsequence;
3118 }
3119
3120 void R_SkinFrame_Purge(void)
3121 {
3122         int i;
3123         skinframe_t *s;
3124         for (i = 0;i < SKINFRAME_HASH;i++)
3125         {
3126                 for (s = r_skinframe.hash[i];s;s = s->next)
3127                 {
3128                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3129                         {
3130                                 if (s->merged == s->base)
3131                                         s->merged = NULL;
3132                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3133                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3134                                 R_PurgeTexture(s->merged);s->merged = NULL;
3135                                 R_PurgeTexture(s->base  );s->base   = NULL;
3136                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3137                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3138                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3139                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3140                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3141                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3142                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3143                                 s->loadsequence = 0;
3144                         }
3145                 }
3146         }
3147 }
3148
3149 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3150         skinframe_t *item;
3151         char basename[MAX_QPATH];
3152
3153         Image_StripImageExtension(name, basename, sizeof(basename));
3154
3155         if( last == NULL ) {
3156                 int hashindex;
3157                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3158                 item = r_skinframe.hash[hashindex];
3159         } else {
3160                 item = last->next;
3161         }
3162
3163         // linearly search through the hash bucket
3164         for( ; item ; item = item->next ) {
3165                 if( !strcmp( item->basename, basename ) ) {
3166                         return item;
3167                 }
3168         }
3169         return NULL;
3170 }
3171
3172 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3173 {
3174         skinframe_t *item;
3175         int hashindex;
3176         char basename[MAX_QPATH];
3177
3178         Image_StripImageExtension(name, basename, sizeof(basename));
3179
3180         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3181         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3182                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3183                         break;
3184
3185         if (!item) {
3186                 rtexture_t *dyntexture;
3187                 // check whether its a dynamic texture
3188                 dyntexture = CL_GetDynTexture( basename );
3189                 if (!add && !dyntexture)
3190                         return NULL;
3191                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3192                 memset(item, 0, sizeof(*item));
3193                 strlcpy(item->basename, basename, sizeof(item->basename));
3194                 item->base = dyntexture; // either NULL or dyntexture handle
3195                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3196                 item->comparewidth = comparewidth;
3197                 item->compareheight = compareheight;
3198                 item->comparecrc = comparecrc;
3199                 item->next = r_skinframe.hash[hashindex];
3200                 r_skinframe.hash[hashindex] = item;
3201         }
3202         else if (textureflags & TEXF_FORCE_RELOAD)
3203         {
3204                 rtexture_t *dyntexture;
3205                 // check whether its a dynamic texture
3206                 dyntexture = CL_GetDynTexture( basename );
3207                 if (!add && !dyntexture)
3208                         return NULL;
3209                 if (item->merged == item->base)
3210                         item->merged = NULL;
3211                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3212                 R_PurgeTexture(item->stain );item->stain  = NULL;
3213                 R_PurgeTexture(item->merged);item->merged = NULL;
3214                 R_PurgeTexture(item->base  );item->base   = NULL;
3215                 R_PurgeTexture(item->pants );item->pants  = NULL;
3216                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3217                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3218                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3219                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3220                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3221         R_PurgeTexture(item->reflect);item->reflect = NULL;
3222                 item->loadsequence = 0;
3223         }
3224         else if( item->base == NULL )
3225         {
3226                 rtexture_t *dyntexture;
3227                 // check whether its a dynamic texture
3228                 // 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]
3229                 dyntexture = CL_GetDynTexture( basename );
3230                 item->base = dyntexture; // either NULL or dyntexture handle
3231         }
3232
3233         R_SkinFrame_MarkUsed(item);
3234         return item;
3235 }
3236
3237 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3238         { \
3239                 unsigned long long avgcolor[5], wsum; \
3240                 int pix, comp, w; \
3241                 avgcolor[0] = 0; \
3242                 avgcolor[1] = 0; \
3243                 avgcolor[2] = 0; \
3244                 avgcolor[3] = 0; \
3245                 avgcolor[4] = 0; \
3246                 wsum = 0; \
3247                 for(pix = 0; pix < cnt; ++pix) \
3248                 { \
3249                         w = 0; \
3250                         for(comp = 0; comp < 3; ++comp) \
3251                                 w += getpixel; \
3252                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3253                         { \
3254                                 ++wsum; \
3255                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3256                                 w = getpixel; \
3257                                 for(comp = 0; comp < 3; ++comp) \
3258                                         avgcolor[comp] += getpixel * w; \
3259                                 avgcolor[3] += w; \
3260                         } \
3261                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3262                         avgcolor[4] += getpixel; \
3263                 } \
3264                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3265                         avgcolor[3] = 1; \
3266                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3267                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3268                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3269                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3270         }
3271
3272 extern cvar_t gl_picmip;
3273 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3274 {
3275         int j;
3276         unsigned char *pixels;
3277         unsigned char *bumppixels;
3278         unsigned char *basepixels = NULL;
3279         int basepixels_width = 0;
3280         int basepixels_height = 0;
3281         skinframe_t *skinframe;
3282         rtexture_t *ddsbase = NULL;
3283         qboolean ddshasalpha = false;
3284         float ddsavgcolor[4];
3285         char basename[MAX_QPATH];
3286         int miplevel = R_PicmipForFlags(textureflags);
3287         int savemiplevel = miplevel;
3288         int mymiplevel;
3289         char vabuf[1024];
3290
3291         if (cls.state == ca_dedicated)
3292                 return NULL;
3293
3294         // return an existing skinframe if already loaded
3295         // if loading of the first image fails, don't make a new skinframe as it
3296         // would cause all future lookups of this to be missing
3297         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3298         if (skinframe && skinframe->base)
3299                 return skinframe;
3300
3301         Image_StripImageExtension(name, basename, sizeof(basename));
3302
3303         // check for DDS texture file first
3304         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3305         {
3306                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3307                 if (basepixels == NULL)
3308                         return NULL;
3309         }
3310
3311         // FIXME handle miplevel
3312
3313         if (developer_loading.integer)
3314                 Con_Printf("loading skin \"%s\"\n", name);
3315
3316         // we've got some pixels to store, so really allocate this new texture now
3317         if (!skinframe)
3318                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3319         textureflags &= ~TEXF_FORCE_RELOAD;
3320         skinframe->stain = NULL;
3321         skinframe->merged = NULL;
3322         skinframe->base = NULL;
3323         skinframe->pants = NULL;
3324         skinframe->shirt = NULL;
3325         skinframe->nmap = NULL;
3326         skinframe->gloss = NULL;
3327         skinframe->glow = NULL;
3328         skinframe->fog = NULL;
3329         skinframe->reflect = NULL;
3330         skinframe->hasalpha = false;
3331
3332         if (ddsbase)
3333         {
3334                 skinframe->base = ddsbase;
3335                 skinframe->hasalpha = ddshasalpha;
3336                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3337                 if (r_loadfog && skinframe->hasalpha)
3338                         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);
3339                 //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]);
3340         }
3341         else
3342         {
3343                 basepixels_width = image_width;
3344                 basepixels_height = image_height;
3345                 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);
3346                 if (textureflags & TEXF_ALPHA)
3347                 {
3348                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3349                         {
3350                                 if (basepixels[j] < 255)
3351                                 {
3352                                         skinframe->hasalpha = true;
3353                                         break;
3354                                 }
3355                         }
3356                         if (r_loadfog && skinframe->hasalpha)
3357                         {
3358                                 // has transparent pixels
3359                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3360                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3361                                 {
3362                                         pixels[j+0] = 255;
3363                                         pixels[j+1] = 255;
3364                                         pixels[j+2] = 255;
3365                                         pixels[j+3] = basepixels[j+3];
3366                                 }
3367                                 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);
3368                                 Mem_Free(pixels);
3369                         }
3370                 }
3371                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3372 #ifndef USE_GLES2
3373                 //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]);
3374                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3375                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3376                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3377                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3378 #endif
3379         }
3380
3381         if (r_loaddds)
3382         {
3383                 mymiplevel = savemiplevel;
3384                 if (r_loadnormalmap)
3385                         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);
3386                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3387                 if (r_loadgloss)
3388                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3389                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3390                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3391                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3392         }
3393
3394         // _norm is the name used by tenebrae and has been adopted as standard
3395         if (r_loadnormalmap && skinframe->nmap == NULL)
3396         {
3397                 mymiplevel = savemiplevel;
3398                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3399                 {
3400                         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);
3401                         Mem_Free(pixels);
3402                         pixels = NULL;
3403                 }
3404                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3405                 {
3406                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3407                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3408                         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);
3409                         Mem_Free(pixels);
3410                         Mem_Free(bumppixels);
3411                 }
3412                 else if (r_shadow_bumpscale_basetexture.value > 0)
3413                 {
3414                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3415                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3416                         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);
3417                         Mem_Free(pixels);
3418                 }
3419 #ifndef USE_GLES2
3420                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3421                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3422 #endif
3423         }
3424
3425         // _luma is supported only for tenebrae compatibility
3426         // _glow is the preferred name
3427         mymiplevel = savemiplevel;
3428         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))))
3429         {
3430                 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);
3431 #ifndef USE_GLES2
3432                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3433                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3434 #endif
3435                 Mem_Free(pixels);pixels = NULL;
3436         }
3437
3438         mymiplevel = savemiplevel;
3439         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3440         {
3441                 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);
3442 #ifndef USE_GLES2
3443                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3444                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3445 #endif
3446                 Mem_Free(pixels);
3447                 pixels = NULL;
3448         }
3449
3450         mymiplevel = savemiplevel;
3451         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3452         {
3453                 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);
3454 #ifndef USE_GLES2
3455                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3456                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3457 #endif
3458                 Mem_Free(pixels);
3459                 pixels = NULL;
3460         }
3461
3462         mymiplevel = savemiplevel;
3463         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3464         {
3465                 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);
3466 #ifndef USE_GLES2
3467                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3468                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3469 #endif
3470                 Mem_Free(pixels);
3471                 pixels = NULL;
3472         }
3473
3474         mymiplevel = savemiplevel;
3475         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3476         {
3477                 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);
3478 #ifndef USE_GLES2
3479                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3480                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3481 #endif
3482                 Mem_Free(pixels);
3483                 pixels = NULL;
3484         }
3485
3486         if (basepixels)
3487                 Mem_Free(basepixels);
3488
3489         return skinframe;
3490 }
3491
3492 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3493 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3494 {
3495         int i;
3496         unsigned char *temp1, *temp2;
3497         skinframe_t *skinframe;
3498         char vabuf[1024];
3499
3500         if (cls.state == ca_dedicated)
3501                 return NULL;
3502
3503         // if already loaded just return it, otherwise make a new skinframe
3504         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3505         if (skinframe->base)
3506                 return skinframe;
3507         textureflags &= ~TEXF_FORCE_RELOAD;
3508
3509         skinframe->stain = NULL;
3510         skinframe->merged = NULL;
3511         skinframe->base = NULL;
3512         skinframe->pants = NULL;
3513         skinframe->shirt = NULL;
3514         skinframe->nmap = NULL;
3515         skinframe->gloss = NULL;
3516         skinframe->glow = NULL;
3517         skinframe->fog = NULL;
3518         skinframe->reflect = NULL;
3519         skinframe->hasalpha = false;
3520
3521         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3522         if (!skindata)
3523                 return NULL;
3524
3525         if (developer_loading.integer)
3526                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3527
3528         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3529         {
3530                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3531                 temp2 = temp1 + width * height * 4;
3532                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3533                 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);
3534                 Mem_Free(temp1);
3535         }
3536         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3537         if (textureflags & TEXF_ALPHA)
3538         {
3539                 for (i = 3;i < width * height * 4;i += 4)
3540                 {
3541                         if (skindata[i] < 255)
3542                         {
3543                                 skinframe->hasalpha = true;
3544                                 break;
3545                         }
3546                 }
3547                 if (r_loadfog && skinframe->hasalpha)
3548                 {
3549                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3550                         memcpy(fogpixels, skindata, width * height * 4);
3551                         for (i = 0;i < width * height * 4;i += 4)
3552                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3553                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3554                         Mem_Free(fogpixels);
3555                 }
3556         }
3557
3558         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3559         //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]);
3560
3561         return skinframe;
3562 }
3563
3564 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3565 {
3566         int i;
3567         int featuresmask;
3568         skinframe_t *skinframe;
3569
3570         if (cls.state == ca_dedicated)
3571                 return NULL;
3572
3573         // if already loaded just return it, otherwise make a new skinframe
3574         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3575         if (skinframe->base)
3576                 return skinframe;
3577         //textureflags &= ~TEXF_FORCE_RELOAD;
3578
3579         skinframe->stain = NULL;
3580         skinframe->merged = NULL;
3581         skinframe->base = NULL;
3582         skinframe->pants = NULL;
3583         skinframe->shirt = NULL;
3584         skinframe->nmap = NULL;
3585         skinframe->gloss = NULL;
3586         skinframe->glow = NULL;
3587         skinframe->fog = NULL;
3588         skinframe->reflect = NULL;
3589         skinframe->hasalpha = false;
3590
3591         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3592         if (!skindata)
3593                 return NULL;
3594
3595         if (developer_loading.integer)
3596                 Con_Printf("loading quake skin \"%s\"\n", name);
3597
3598         // 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)
3599         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3600         memcpy(skinframe->qpixels, skindata, width*height);
3601         skinframe->qwidth = width;
3602         skinframe->qheight = height;
3603
3604         featuresmask = 0;
3605         for (i = 0;i < width * height;i++)
3606                 featuresmask |= palette_featureflags[skindata[i]];
3607
3608         skinframe->hasalpha = false;
3609         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3610         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3611         skinframe->qgeneratemerged = true;
3612         skinframe->qgeneratebase = skinframe->qhascolormapping;
3613         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3614
3615         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3616         //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]);
3617
3618         return skinframe;
3619 }
3620
3621 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3622 {
3623         int width;
3624         int height;
3625         unsigned char *skindata;
3626         char vabuf[1024];
3627
3628         if (!skinframe->qpixels)
3629                 return;
3630
3631         if (!skinframe->qhascolormapping)
3632                 colormapped = false;
3633
3634         if (colormapped)
3635         {
3636                 if (!skinframe->qgeneratebase)
3637                         return;
3638         }
3639         else
3640         {
3641                 if (!skinframe->qgeneratemerged)
3642                         return;
3643         }
3644
3645         width = skinframe->qwidth;
3646         height = skinframe->qheight;
3647         skindata = skinframe->qpixels;
3648
3649         if (skinframe->qgeneratenmap)
3650         {
3651                 unsigned char *temp1, *temp2;
3652                 skinframe->qgeneratenmap = false;
3653                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3654                 temp2 = temp1 + width * height * 4;
3655                 // use either a custom palette or the quake palette
3656                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3657                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3658                 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);
3659                 Mem_Free(temp1);
3660         }
3661
3662         if (skinframe->qgenerateglow)
3663         {
3664                 skinframe->qgenerateglow = false;
3665                 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
3666         }
3667
3668         if (colormapped)
3669         {
3670                 skinframe->qgeneratebase = false;
3671                 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);
3672                 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);
3673                 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);
3674         }
3675         else
3676         {
3677                 skinframe->qgeneratemerged = false;
3678                 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);
3679         }
3680
3681         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3682         {
3683                 Mem_Free(skinframe->qpixels);
3684                 skinframe->qpixels = NULL;
3685         }
3686 }
3687
3688 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)
3689 {
3690         int i;
3691         skinframe_t *skinframe;
3692         char vabuf[1024];
3693
3694         if (cls.state == ca_dedicated)
3695                 return NULL;
3696
3697         // if already loaded just return it, otherwise make a new skinframe
3698         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3699         if (skinframe->base)
3700                 return skinframe;
3701         textureflags &= ~TEXF_FORCE_RELOAD;
3702
3703         skinframe->stain = NULL;
3704         skinframe->merged = NULL;
3705         skinframe->base = NULL;
3706         skinframe->pants = NULL;
3707         skinframe->shirt = NULL;
3708         skinframe->nmap = NULL;
3709         skinframe->gloss = NULL;
3710         skinframe->glow = NULL;
3711         skinframe->fog = NULL;
3712         skinframe->reflect = NULL;
3713         skinframe->hasalpha = false;
3714
3715         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3716         if (!skindata)
3717                 return NULL;
3718
3719         if (developer_loading.integer)
3720                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3721
3722         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3723         if (textureflags & TEXF_ALPHA)
3724         {
3725                 for (i = 0;i < width * height;i++)
3726                 {
3727                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3728                         {
3729                                 skinframe->hasalpha = true;
3730                                 break;
3731                         }
3732                 }
3733                 if (r_loadfog && skinframe->hasalpha)
3734                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3735         }
3736
3737         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3738         //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]);
3739
3740         return skinframe;
3741 }
3742
3743 skinframe_t *R_SkinFrame_LoadMissing(void)
3744 {
3745         skinframe_t *skinframe;
3746
3747         if (cls.state == ca_dedicated)
3748                 return NULL;
3749
3750         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3751         skinframe->stain = NULL;
3752         skinframe->merged = NULL;
3753         skinframe->base = NULL;
3754         skinframe->pants = NULL;
3755         skinframe->shirt = NULL;
3756         skinframe->nmap = NULL;
3757         skinframe->gloss = NULL;
3758         skinframe->glow = NULL;
3759         skinframe->fog = NULL;
3760         skinframe->reflect = NULL;
3761         skinframe->hasalpha = false;
3762
3763         skinframe->avgcolor[0] = rand() / RAND_MAX;
3764         skinframe->avgcolor[1] = rand() / RAND_MAX;
3765         skinframe->avgcolor[2] = rand() / RAND_MAX;
3766         skinframe->avgcolor[3] = 1;
3767
3768         return skinframe;
3769 }
3770
3771 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3772 typedef struct suffixinfo_s
3773 {
3774         const char *suffix;
3775         qboolean flipx, flipy, flipdiagonal;
3776 }
3777 suffixinfo_t;
3778 static suffixinfo_t suffix[3][6] =
3779 {
3780         {
3781                 {"px",   false, false, false},
3782                 {"nx",   false, false, false},
3783                 {"py",   false, false, false},
3784                 {"ny",   false, false, false},
3785                 {"pz",   false, false, false},
3786                 {"nz",   false, false, false}
3787         },
3788         {
3789                 {"posx", false, false, false},
3790                 {"negx", false, false, false},
3791                 {"posy", false, false, false},
3792                 {"negy", false, false, false},
3793                 {"posz", false, false, false},
3794                 {"negz", false, false, false}
3795         },
3796         {
3797                 {"rt",    true, false,  true},
3798                 {"lf",   false,  true,  true},
3799                 {"ft",    true,  true, false},
3800                 {"bk",   false, false, false},
3801                 {"up",    true, false,  true},
3802                 {"dn",    true, false,  true}
3803         }
3804 };
3805
3806 static int componentorder[4] = {0, 1, 2, 3};
3807
3808 static rtexture_t *R_LoadCubemap(const char *basename)
3809 {
3810         int i, j, cubemapsize;
3811         unsigned char *cubemappixels, *image_buffer;
3812         rtexture_t *cubemaptexture;
3813         char name[256];
3814         // must start 0 so the first loadimagepixels has no requested width/height
3815         cubemapsize = 0;
3816         cubemappixels = NULL;
3817         cubemaptexture = NULL;
3818         // keep trying different suffix groups (posx, px, rt) until one loads
3819         for (j = 0;j < 3 && !cubemappixels;j++)
3820         {
3821                 // load the 6 images in the suffix group
3822                 for (i = 0;i < 6;i++)
3823                 {
3824                         // generate an image name based on the base and and suffix
3825                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3826                         // load it
3827                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3828                         {
3829                                 // an image loaded, make sure width and height are equal
3830                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3831                                 {
3832                                         // if this is the first image to load successfully, allocate the cubemap memory
3833                                         if (!cubemappixels && image_width >= 1)
3834                                         {
3835                                                 cubemapsize = image_width;
3836                                                 // note this clears to black, so unavailable sides are black
3837                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3838                                         }
3839                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3840                                         if (cubemappixels)
3841                                                 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);
3842                                 }
3843                                 else
3844                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3845                                 // free the image
3846                                 Mem_Free(image_buffer);
3847                         }
3848                 }
3849         }
3850         // if a cubemap loaded, upload it
3851         if (cubemappixels)
3852         {
3853                 if (developer_loading.integer)
3854                         Con_Printf("loading cubemap \"%s\"\n", basename);
3855
3856                 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);
3857                 Mem_Free(cubemappixels);
3858         }
3859         else
3860         {
3861                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3862                 if (developer_loading.integer)
3863                 {
3864                         Con_Printf("(tried tried images ");
3865                         for (j = 0;j < 3;j++)
3866                                 for (i = 0;i < 6;i++)
3867                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3868                         Con_Print(" and was unable to find any of them).\n");
3869                 }
3870         }
3871         return cubemaptexture;
3872 }
3873
3874 rtexture_t *R_GetCubemap(const char *basename)
3875 {
3876         int i;
3877         for (i = 0;i < r_texture_numcubemaps;i++)
3878                 if (r_texture_cubemaps[i] != NULL)
3879                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3880                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3881         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3882                 return r_texture_whitecube;
3883         r_texture_numcubemaps++;
3884         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3885         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3886         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3887         return r_texture_cubemaps[i]->texture;
3888 }
3889
3890 static void R_Main_FreeViewCache(void)
3891 {
3892         if (r_refdef.viewcache.entityvisible)
3893                 Mem_Free(r_refdef.viewcache.entityvisible);
3894         if (r_refdef.viewcache.world_pvsbits)
3895                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3896         if (r_refdef.viewcache.world_leafvisible)
3897                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3898         if (r_refdef.viewcache.world_surfacevisible)
3899                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3900         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3901 }
3902
3903 static void R_Main_ResizeViewCache(void)
3904 {
3905         int numentities = r_refdef.scene.numentities;
3906         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3907         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3908         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3909         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3910         if (r_refdef.viewcache.maxentities < numentities)
3911         {
3912                 r_refdef.viewcache.maxentities = numentities;
3913                 if (r_refdef.viewcache.entityvisible)
3914                         Mem_Free(r_refdef.viewcache.entityvisible);
3915                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3916         }
3917         if (r_refdef.viewcache.world_numclusters != numclusters)
3918         {
3919                 r_refdef.viewcache.world_numclusters = numclusters;
3920                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3921                 if (r_refdef.viewcache.world_pvsbits)
3922                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3923                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3924         }
3925         if (r_refdef.viewcache.world_numleafs != numleafs)
3926         {
3927                 r_refdef.viewcache.world_numleafs = numleafs;
3928                 if (r_refdef.viewcache.world_leafvisible)
3929                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3930                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3931         }
3932         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3933         {
3934                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3935                 if (r_refdef.viewcache.world_surfacevisible)
3936                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3937                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3938         }
3939 }
3940
3941 extern rtexture_t *loadingscreentexture;
3942 static void gl_main_start(void)
3943 {
3944         loadingscreentexture = NULL;
3945         r_texture_blanknormalmap = NULL;
3946         r_texture_white = NULL;
3947         r_texture_grey128 = NULL;
3948         r_texture_black = NULL;
3949         r_texture_whitecube = NULL;
3950         r_texture_normalizationcube = NULL;
3951         r_texture_fogattenuation = NULL;
3952         r_texture_fogheighttexture = NULL;
3953         r_texture_gammaramps = NULL;
3954         r_texture_numcubemaps = 0;
3955
3956         r_loaddds = r_texture_dds_load.integer != 0;
3957         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3958
3959         switch(vid.renderpath)
3960         {
3961         case RENDERPATH_GL20:
3962         case RENDERPATH_D3D9:
3963         case RENDERPATH_D3D10:
3964         case RENDERPATH_D3D11:
3965         case RENDERPATH_SOFT:
3966         case RENDERPATH_GLES2:
3967                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3968                 Cvar_SetValueQuick(&gl_combine, 1);
3969                 Cvar_SetValueQuick(&r_glsl, 1);
3970                 r_loadnormalmap = true;
3971                 r_loadgloss = true;
3972                 r_loadfog = false;
3973                 break;
3974         case RENDERPATH_GL13:
3975         case RENDERPATH_GLES1:
3976                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3977                 Cvar_SetValueQuick(&gl_combine, 1);
3978                 Cvar_SetValueQuick(&r_glsl, 0);
3979                 r_loadnormalmap = false;
3980                 r_loadgloss = false;
3981                 r_loadfog = true;
3982                 break;
3983         case RENDERPATH_GL11:
3984                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3985                 Cvar_SetValueQuick(&gl_combine, 0);
3986                 Cvar_SetValueQuick(&r_glsl, 0);
3987                 r_loadnormalmap = false;
3988                 r_loadgloss = false;
3989                 r_loadfog = true;
3990                 break;
3991         }
3992
3993         R_AnimCache_Free();
3994         R_FrameData_Reset();
3995
3996         r_numqueries = 0;
3997         r_maxqueries = 0;
3998         memset(r_queries, 0, sizeof(r_queries));
3999
4000         r_qwskincache = NULL;
4001         r_qwskincache_size = 0;
4002
4003         // due to caching of texture_t references, the collision cache must be reset
4004         Collision_Cache_Reset(true);
4005
4006         // set up r_skinframe loading system for textures
4007         memset(&r_skinframe, 0, sizeof(r_skinframe));
4008         r_skinframe.loadsequence = 1;
4009         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4010
4011         r_main_texturepool = R_AllocTexturePool();
4012         R_BuildBlankTextures();
4013         R_BuildNoTexture();
4014         if (vid.support.arb_texture_cube_map)
4015         {
4016                 R_BuildWhiteCube();
4017                 R_BuildNormalizationCube();
4018         }
4019         r_texture_fogattenuation = NULL;
4020         r_texture_fogheighttexture = NULL;
4021         r_texture_gammaramps = NULL;
4022         //r_texture_fogintensity = NULL;
4023         memset(&r_fb, 0, sizeof(r_fb));
4024         r_glsl_permutation = NULL;
4025         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4026         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4027         glslshaderstring = NULL;
4028 #ifdef SUPPORTD3D
4029         r_hlsl_permutation = NULL;
4030         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4031         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4032 #endif
4033         hlslshaderstring = NULL;
4034         memset(&r_svbsp, 0, sizeof (r_svbsp));
4035
4036         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4037         r_texture_numcubemaps = 0;
4038
4039         r_refdef.fogmasktable_density = 0;
4040 }
4041
4042 static void gl_main_shutdown(void)
4043 {
4044         R_AnimCache_Free();
4045         R_FrameData_Reset();
4046
4047         R_Main_FreeViewCache();
4048
4049         switch(vid.renderpath)
4050         {
4051         case RENDERPATH_GL11:
4052         case RENDERPATH_GL13:
4053         case RENDERPATH_GL20:
4054         case RENDERPATH_GLES1:
4055         case RENDERPATH_GLES2:
4056 #ifdef GL_SAMPLES_PASSED_ARB
4057                 if (r_maxqueries)
4058                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4059 #endif
4060                 break;
4061         case RENDERPATH_D3D9:
4062                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4063                 break;
4064         case RENDERPATH_D3D10:
4065                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4066                 break;
4067         case RENDERPATH_D3D11:
4068                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4069                 break;
4070         case RENDERPATH_SOFT:
4071                 break;
4072         }
4073
4074         r_numqueries = 0;
4075         r_maxqueries = 0;
4076         memset(r_queries, 0, sizeof(r_queries));
4077
4078         r_qwskincache = NULL;
4079         r_qwskincache_size = 0;
4080
4081         // clear out the r_skinframe state
4082         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4083         memset(&r_skinframe, 0, sizeof(r_skinframe));
4084
4085         if (r_svbsp.nodes)
4086                 Mem_Free(r_svbsp.nodes);
4087         memset(&r_svbsp, 0, sizeof (r_svbsp));
4088         R_FreeTexturePool(&r_main_texturepool);
4089         loadingscreentexture = NULL;
4090         r_texture_blanknormalmap = NULL;
4091         r_texture_white = NULL;
4092         r_texture_grey128 = NULL;
4093         r_texture_black = NULL;
4094         r_texture_whitecube = NULL;
4095         r_texture_normalizationcube = NULL;
4096         r_texture_fogattenuation = NULL;
4097         r_texture_fogheighttexture = NULL;
4098         r_texture_gammaramps = NULL;
4099         r_texture_numcubemaps = 0;
4100         //r_texture_fogintensity = NULL;
4101         memset(&r_fb, 0, sizeof(r_fb));
4102         R_GLSL_Restart_f();
4103
4104         r_glsl_permutation = NULL;
4105         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4106         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4107         glslshaderstring = NULL;
4108 #ifdef SUPPORTD3D
4109         r_hlsl_permutation = NULL;
4110         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4111         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4112 #endif
4113         hlslshaderstring = NULL;
4114 }
4115
4116 static void gl_main_newmap(void)
4117 {
4118         // FIXME: move this code to client
4119         char *entities, entname[MAX_QPATH];
4120         if (r_qwskincache)
4121                 Mem_Free(r_qwskincache);
4122         r_qwskincache = NULL;
4123         r_qwskincache_size = 0;
4124         if (cl.worldmodel)
4125         {
4126                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4127                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4128                 {
4129                         CL_ParseEntityLump(entities);
4130                         Mem_Free(entities);
4131                         return;
4132                 }
4133                 if (cl.worldmodel->brush.entities)
4134                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4135         }
4136         R_Main_FreeViewCache();
4137
4138         R_FrameData_Reset();
4139 }
4140
4141 void GL_Main_Init(void)
4142 {
4143         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4144
4145         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4146         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4147         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4148         if (gamemode == GAME_NEHAHRA)
4149         {
4150                 Cvar_RegisterVariable (&gl_fogenable);
4151                 Cvar_RegisterVariable (&gl_fogdensity);
4152                 Cvar_RegisterVariable (&gl_fogred);
4153                 Cvar_RegisterVariable (&gl_foggreen);
4154                 Cvar_RegisterVariable (&gl_fogblue);
4155                 Cvar_RegisterVariable (&gl_fogstart);
4156                 Cvar_RegisterVariable (&gl_fogend);
4157                 Cvar_RegisterVariable (&gl_skyclip);
4158         }
4159         Cvar_RegisterVariable(&r_motionblur);
4160         Cvar_RegisterVariable(&r_damageblur);
4161         Cvar_RegisterVariable(&r_motionblur_averaging);
4162         Cvar_RegisterVariable(&r_motionblur_randomize);
4163         Cvar_RegisterVariable(&r_motionblur_minblur);
4164         Cvar_RegisterVariable(&r_motionblur_maxblur);
4165         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4166         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4167         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4168         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4169         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4170         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4171         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4172         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4173         Cvar_RegisterVariable(&r_equalize_entities_by);
4174         Cvar_RegisterVariable(&r_equalize_entities_to);
4175         Cvar_RegisterVariable(&r_depthfirst);
4176         Cvar_RegisterVariable(&r_useinfinitefarclip);
4177         Cvar_RegisterVariable(&r_farclip_base);
4178         Cvar_RegisterVariable(&r_farclip_world);
4179         Cvar_RegisterVariable(&r_nearclip);
4180         Cvar_RegisterVariable(&r_deformvertexes);
4181         Cvar_RegisterVariable(&r_transparent);
4182         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4183         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4184         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4185         Cvar_RegisterVariable(&r_showoverdraw);
4186         Cvar_RegisterVariable(&r_showbboxes);
4187         Cvar_RegisterVariable(&r_showsurfaces);
4188         Cvar_RegisterVariable(&r_showtris);
4189         Cvar_RegisterVariable(&r_shownormals);
4190         Cvar_RegisterVariable(&r_showlighting);
4191         Cvar_RegisterVariable(&r_showshadowvolumes);
4192         Cvar_RegisterVariable(&r_showcollisionbrushes);
4193         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4194         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4195         Cvar_RegisterVariable(&r_showdisabledepthtest);
4196         Cvar_RegisterVariable(&r_drawportals);
4197         Cvar_RegisterVariable(&r_drawentities);
4198         Cvar_RegisterVariable(&r_draw2d);
4199         Cvar_RegisterVariable(&r_drawworld);
4200         Cvar_RegisterVariable(&r_cullentities_trace);
4201         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4202         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4203         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4204         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4205         Cvar_RegisterVariable(&r_sortentities);
4206         Cvar_RegisterVariable(&r_drawviewmodel);
4207         Cvar_RegisterVariable(&r_drawexteriormodel);
4208         Cvar_RegisterVariable(&r_speeds);
4209         Cvar_RegisterVariable(&r_fullbrights);
4210         Cvar_RegisterVariable(&r_wateralpha);
4211         Cvar_RegisterVariable(&r_dynamic);
4212         Cvar_RegisterVariable(&r_fakelight);
4213         Cvar_RegisterVariable(&r_fakelight_intensity);
4214         Cvar_RegisterVariable(&r_fullbright);
4215         Cvar_RegisterVariable(&r_shadows);
4216         Cvar_RegisterVariable(&r_shadows_darken);
4217         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4218         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4219         Cvar_RegisterVariable(&r_shadows_throwdistance);
4220         Cvar_RegisterVariable(&r_shadows_throwdirection);
4221         Cvar_RegisterVariable(&r_shadows_focus);
4222         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4223         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4224         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4225         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4226         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4227         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4228         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4229         Cvar_RegisterVariable(&r_fog_exp2);
4230         Cvar_RegisterVariable(&r_fog_clear);
4231         Cvar_RegisterVariable(&r_drawfog);
4232         Cvar_RegisterVariable(&r_transparentdepthmasking);
4233         Cvar_RegisterVariable(&r_transparent_sortmindist);
4234         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4235         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4236         Cvar_RegisterVariable(&r_texture_dds_load);
4237         Cvar_RegisterVariable(&r_texture_dds_save);
4238         Cvar_RegisterVariable(&r_textureunits);
4239         Cvar_RegisterVariable(&gl_combine);
4240         Cvar_RegisterVariable(&r_usedepthtextures);
4241         Cvar_RegisterVariable(&r_viewfbo);
4242         Cvar_RegisterVariable(&r_viewscale);
4243         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4244         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4245         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4246         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4247         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4248         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4249         Cvar_RegisterVariable(&r_glsl);
4250         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4251         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4252         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4253         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4254         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4255         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4256         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4257         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4258         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4259         Cvar_RegisterVariable(&r_glsl_postprocess);
4260         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4261         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4262         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4263         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4264         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4265         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4266         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4267         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4268         Cvar_RegisterVariable(&r_celshading);
4269         Cvar_RegisterVariable(&r_celoutlines);
4270
4271         Cvar_RegisterVariable(&r_water);
4272         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4273         Cvar_RegisterVariable(&r_water_clippingplanebias);
4274         Cvar_RegisterVariable(&r_water_refractdistort);
4275         Cvar_RegisterVariable(&r_water_reflectdistort);
4276         Cvar_RegisterVariable(&r_water_scissormode);
4277         Cvar_RegisterVariable(&r_water_lowquality);
4278         Cvar_RegisterVariable(&r_water_hideplayer);
4279         Cvar_RegisterVariable(&r_water_fbo);
4280
4281         Cvar_RegisterVariable(&r_lerpsprites);
4282         Cvar_RegisterVariable(&r_lerpmodels);
4283         Cvar_RegisterVariable(&r_lerplightstyles);
4284         Cvar_RegisterVariable(&r_waterscroll);
4285         Cvar_RegisterVariable(&r_bloom);
4286         Cvar_RegisterVariable(&r_bloom_colorscale);
4287         Cvar_RegisterVariable(&r_bloom_brighten);
4288         Cvar_RegisterVariable(&r_bloom_blur);
4289         Cvar_RegisterVariable(&r_bloom_resolution);
4290         Cvar_RegisterVariable(&r_bloom_colorexponent);
4291         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4292         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4293         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4294         Cvar_RegisterVariable(&r_hdr_glowintensity);
4295         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4296         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4297         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4298         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4299         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4300         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4301         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4302         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4303         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4304         Cvar_RegisterVariable(&developer_texturelogging);
4305         Cvar_RegisterVariable(&gl_lightmaps);
4306         Cvar_RegisterVariable(&r_test);
4307         Cvar_RegisterVariable(&r_batch_multidraw);
4308         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4309         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4310         Cvar_RegisterVariable(&r_glsl_skeletal);
4311         Cvar_RegisterVariable(&r_glsl_saturation);
4312         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4313         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4314         Cvar_RegisterVariable(&r_framedatasize);
4315         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4316                 Cvar_SetValue("r_fullbrights", 0);
4317         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4318 }
4319
4320 void Render_Init(void)
4321 {
4322         gl_backend_init();
4323         R_Textures_Init();
4324         GL_Main_Init();
4325         Font_Init();
4326         GL_Draw_Init();
4327         R_Shadow_Init();
4328         R_Sky_Init();
4329         GL_Surf_Init();
4330         Sbar_Init();
4331         R_Particles_Init();
4332         R_Explosion_Init();
4333         R_LightningBeams_Init();
4334         Mod_RenderInit();
4335 }
4336
4337 /*
4338 ===============
4339 GL_Init
4340 ===============
4341 */
4342 #ifndef USE_GLES2
4343 extern char *ENGINE_EXTENSIONS;
4344 void GL_Init (void)
4345 {
4346         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4347         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4348         gl_version = (const char *)qglGetString(GL_VERSION);
4349         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4350
4351         if (!gl_extensions)
4352                 gl_extensions = "";
4353         if (!gl_platformextensions)
4354                 gl_platformextensions = "";
4355
4356         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4357         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4358         Con_Printf("GL_VERSION: %s\n", gl_version);
4359         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4360         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4361
4362         VID_CheckExtensions();
4363
4364         // LordHavoc: report supported extensions
4365         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4366
4367         // clear to black (loading plaque will be seen over this)
4368         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4369 }
4370 #endif
4371
4372 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4373 {
4374         int i;
4375         mplane_t *p;
4376         if (r_trippy.integer)
4377                 return false;
4378         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4379         {
4380                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4381                 if (i == 4)
4382                         continue;
4383                 p = r_refdef.view.frustum + i;
4384                 switch(p->signbits)
4385                 {
4386                 default:
4387                 case 0:
4388                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4389                                 return true;
4390                         break;
4391                 case 1:
4392                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4393                                 return true;
4394                         break;
4395                 case 2:
4396                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4397                                 return true;
4398                         break;
4399                 case 3:
4400                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4401                                 return true;
4402                         break;
4403                 case 4:
4404                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4405                                 return true;
4406                         break;
4407                 case 5:
4408                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4409                                 return true;
4410                         break;
4411                 case 6:
4412                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4413                                 return true;
4414                         break;
4415                 case 7:
4416                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4417                                 return true;
4418                         break;
4419                 }
4420         }
4421         return false;
4422 }
4423
4424 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4425 {
4426         int i;
4427         const mplane_t *p;
4428         if (r_trippy.integer)
4429                 return false;
4430         for (i = 0;i < numplanes;i++)
4431         {
4432                 p = planes + i;
4433                 switch(p->signbits)
4434                 {
4435                 default:
4436                 case 0:
4437                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4438                                 return true;
4439                         break;
4440                 case 1:
4441                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4442                                 return true;
4443                         break;
4444                 case 2:
4445                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4446                                 return true;
4447                         break;
4448                 case 3:
4449                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4450                                 return true;
4451                         break;
4452                 case 4:
4453                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4454                                 return true;
4455                         break;
4456                 case 5:
4457                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4458                                 return true;
4459                         break;
4460                 case 6:
4461                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4462                                 return true;
4463                         break;
4464                 case 7:
4465                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4466                                 return true;
4467                         break;
4468                 }
4469         }
4470         return false;
4471 }
4472
4473 //==================================================================================
4474
4475 // LordHavoc: this stores temporary data used within the same frame
4476
4477 typedef struct r_framedata_mem_s
4478 {
4479         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4480         size_t size; // how much usable space
4481         size_t current; // how much space in use
4482         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4483         size_t wantedsize; // how much space was allocated
4484         unsigned char *data; // start of real data (16byte aligned)
4485 }
4486 r_framedata_mem_t;
4487
4488 static r_framedata_mem_t *r_framedata_mem;
4489
4490 void R_FrameData_Reset(void)
4491 {
4492         while (r_framedata_mem)
4493         {
4494                 r_framedata_mem_t *next = r_framedata_mem->purge;
4495                 Mem_Free(r_framedata_mem);
4496                 r_framedata_mem = next;
4497         }
4498 }
4499
4500 static void R_FrameData_Resize(void)
4501 {
4502         size_t wantedsize;
4503         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4504         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4505         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4506         {
4507                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4508                 newmem->wantedsize = wantedsize;
4509                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4510                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4511                 newmem->current = 0;
4512                 newmem->mark = 0;
4513                 newmem->purge = r_framedata_mem;
4514                 r_framedata_mem = newmem;
4515         }
4516 }
4517
4518 void R_FrameData_NewFrame(void)
4519 {
4520         R_FrameData_Resize();
4521         if (!r_framedata_mem)
4522                 return;
4523         // if we ran out of space on the last frame, free the old memory now
4524         while (r_framedata_mem->purge)
4525         {
4526                 // repeatedly remove the second item in the list, leaving only head
4527                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4528                 Mem_Free(r_framedata_mem->purge);
4529                 r_framedata_mem->purge = next;
4530         }
4531         // reset the current mem pointer
4532         r_framedata_mem->current = 0;
4533         r_framedata_mem->mark = 0;
4534 }
4535
4536 void *R_FrameData_Alloc(size_t size)
4537 {
4538         void *data;
4539
4540         // align to 16 byte boundary - the data pointer is already aligned, so we
4541         // only need to ensure the size of every allocation is also aligned
4542         size = (size + 15) & ~15;
4543
4544         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4545         {
4546                 // emergency - we ran out of space, allocate more memory
4547                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4548                 R_FrameData_Resize();
4549         }
4550
4551         data = r_framedata_mem->data + r_framedata_mem->current;
4552         r_framedata_mem->current += size;
4553
4554         // count the usage for stats
4555         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4556         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4557
4558         return (void *)data;
4559 }
4560
4561 void *R_FrameData_Store(size_t size, void *data)
4562 {
4563         void *d = R_FrameData_Alloc(size);
4564         if (d && data)
4565                 memcpy(d, data, size);
4566         return d;
4567 }
4568
4569 void R_FrameData_SetMark(void)
4570 {
4571         if (!r_framedata_mem)
4572                 return;
4573         r_framedata_mem->mark = r_framedata_mem->current;
4574 }
4575
4576 void R_FrameData_ReturnToMark(void)
4577 {
4578         if (!r_framedata_mem)
4579                 return;
4580         r_framedata_mem->current = r_framedata_mem->mark;
4581 }
4582
4583 //==================================================================================
4584
4585 // LordHavoc: animcache originally written by Echon, rewritten since then
4586
4587 /**
4588  * Animation cache prevents re-generating mesh data for an animated model
4589  * multiple times in one frame for lighting, shadowing, reflections, etc.
4590  */
4591
4592 void R_AnimCache_Free(void)
4593 {
4594 }
4595
4596 void R_AnimCache_ClearCache(void)
4597 {
4598         int i;
4599         entity_render_t *ent;
4600
4601         for (i = 0;i < r_refdef.scene.numentities;i++)
4602         {
4603                 ent = r_refdef.scene.entities[i];
4604                 ent->animcache_vertex3f = NULL;
4605                 ent->animcache_normal3f = NULL;
4606                 ent->animcache_svector3f = NULL;
4607                 ent->animcache_tvector3f = NULL;
4608                 ent->animcache_vertexmesh = NULL;
4609                 ent->animcache_vertex3fbuffer = NULL;
4610                 ent->animcache_vertexmeshbuffer = NULL;
4611                 ent->animcache_skeletaltransform3x4 = NULL;
4612         }
4613 }
4614
4615 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4616 {
4617         int i;
4618
4619         // check if we need the meshbuffers
4620         if (!vid.useinterleavedarrays)
4621                 return;
4622
4623         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4624                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4625         // TODO: upload vertex3f buffer?
4626         if (ent->animcache_vertexmesh)
4627         {
4628                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4629                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4630                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4631                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4632                 for (i = 0;i < numvertices;i++)
4633                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4634                 if (ent->animcache_svector3f)
4635                         for (i = 0;i < numvertices;i++)
4636                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4637                 if (ent->animcache_tvector3f)
4638                         for (i = 0;i < numvertices;i++)
4639                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4640                 if (ent->animcache_normal3f)
4641                         for (i = 0;i < numvertices;i++)
4642                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4643                 // TODO: upload vertexmeshbuffer?
4644         }
4645 }
4646
4647 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4648 {
4649         dp_model_t *model = ent->model;
4650         int numvertices;
4651
4652         // see if this ent is worth caching
4653         if (!model || !model->Draw || !model->AnimateVertices)
4654                 return false;
4655         // nothing to cache if it contains no animations and has no skeleton
4656         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4657                 return false;
4658         // see if it is already cached for gpuskeletal
4659         if (ent->animcache_skeletaltransform3x4)
4660                 return false;
4661         // see if it is already cached as a mesh
4662         if (ent->animcache_vertex3f)
4663         {
4664                 // check if we need to add normals or tangents
4665                 if (ent->animcache_normal3f)
4666                         wantnormals = false;
4667                 if (ent->animcache_svector3f)
4668                         wanttangents = false;
4669                 if (!wantnormals && !wanttangents)
4670                         return false;
4671         }
4672
4673         // check which kind of cache we need to generate
4674         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4675         {
4676                 // cache the skeleton so the vertex shader can use it
4677                 int i;
4678                 int blends;
4679                 const skeleton_t *skeleton = ent->skeleton;
4680                 const frameblend_t *frameblend = ent->frameblend;
4681                 float *boneposerelative;
4682                 float m[12];
4683                 static float bonepose[256][12];
4684                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4685                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4686                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4687                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4688                 boneposerelative = ent->animcache_skeletaltransform3x4;
4689                 if (skeleton && !skeleton->relativetransforms)
4690                         skeleton = NULL;
4691                 // resolve hierarchy and make relative transforms (deforms) which the shader wants
4692                 if (skeleton)
4693                 {
4694                         for (i = 0;i < model->num_bones;i++)
4695                         {
4696                                 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
4697                                 if (model->data_bones[i].parent >= 0)
4698                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4699                                 else
4700                                         memcpy(bonepose[i], m, sizeof(m));
4701
4702                                 // create a relative deformation matrix to describe displacement
4703                                 // from the base mesh, which is used by the actual weighting
4704                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4705                         }
4706                 }
4707                 else
4708                 {
4709                         for (i = 0;i < model->num_bones;i++)
4710                         {
4711                                 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
4712                                 float lerp = frameblend[0].lerp,
4713                                         tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4714                                         rx = pose7s[3] * lerp,
4715                                         ry = pose7s[4] * lerp,
4716                                         rz = pose7s[5] * lerp,
4717                                         rw = pose7s[6] * lerp,
4718                                         dx = tx*rw + ty*rz - tz*ry,
4719                                         dy = -tx*rz + ty*rw + tz*rx,
4720                                         dz = tx*ry - ty*rx + tz*rw,
4721                                         dw = -tx*rx - ty*ry - tz*rz,
4722                                         scale, sx, sy, sz, sw;
4723                                 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
4724                                 {
4725                                         const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
4726                                         float lerp = frameblend[blends].lerp,
4727                                                 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4728                                                 qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
4729                                         if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
4730                                         qx *= lerp;
4731                                         qy *= lerp;
4732                                         qz *= lerp;
4733                                         qw *= lerp;
4734                                         rx += qx;
4735                                         ry += qy;
4736                                         rz += qz;
4737                                         rw += qw;
4738                                         dx += tx*qw + ty*qz - tz*qy;
4739                                         dy += -tx*qz + ty*qw + tz*qx;
4740                                         dz += tx*qy - ty*qx + tz*qw;
4741                                         dw += -tx*qx - ty*qy - tz*qz;
4742                                 }
4743                                 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
4744                                 sx = rx * scale;
4745                                 sy = ry * scale;
4746                                 sz = rz * scale;
4747                                 sw = rw * scale;
4748                                 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
4749                                 m[1] = 2*(sx*ry - sw*rz);
4750                                 m[2] = 2*(sx*rz + sw*ry);
4751                                 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
4752                                 m[4] = 2*(sx*ry + sw*rz);
4753                                 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
4754                                 m[6] = 2*(sy*rz - sw*rx);
4755                                 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
4756                                 m[8] = 2*(sx*rz - sw*ry);
4757                                 m[9] = 2*(sy*rz + sw*rx);
4758                                 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
4759                                 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
4760                                 if (i == r_skeletal_debugbone.integer)
4761                                         m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
4762                                 m[3] *= r_skeletal_debugtranslatex.value;
4763                                 m[7] *= r_skeletal_debugtranslatey.value;
4764                                 m[11] *= r_skeletal_debugtranslatez.value;
4765                                 if (model->data_bones[i].parent >= 0)
4766                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4767                                 else
4768                                         memcpy(bonepose[i], m, sizeof(m));
4769                                 // create a relative deformation matrix to describe displacement
4770                                 // from the base mesh, which is used by the actual weighting
4771                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4772                         }
4773                 }
4774         }
4775         else if (ent->animcache_vertex3f)
4776         {
4777                 // mesh was already cached but we may need to add normals/tangents
4778                 // (this only happens with multiple views, reflections, cameras, etc)
4779                 if (wantnormals || wanttangents)
4780                 {
4781                         numvertices = model->surfmesh.num_vertices;
4782                         if (wantnormals)
4783                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4784                         if (wanttangents)
4785                         {
4786                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4787                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4788                         }
4789                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4790                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4791                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4792                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4793                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4794                 }
4795         }
4796         else
4797         {
4798                 // generate mesh cache
4799                 numvertices = model->surfmesh.num_vertices;
4800                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4801                 if (wantnormals)
4802                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4803                 if (wanttangents)
4804                 {
4805                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4806                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4807                 }
4808                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4809                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4810                 if (wantnormals || wanttangents)
4811                 {
4812                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4813                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4814                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4815                 }
4816                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4817                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4818                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4819         }
4820         return true;
4821 }
4822
4823 void R_AnimCache_CacheVisibleEntities(void)
4824 {
4825         int i;
4826         qboolean wantnormals = true;
4827         qboolean wanttangents = !r_showsurfaces.integer;
4828
4829         switch(vid.renderpath)
4830         {
4831         case RENDERPATH_GL20:
4832         case RENDERPATH_D3D9:
4833         case RENDERPATH_D3D10:
4834         case RENDERPATH_D3D11:
4835         case RENDERPATH_GLES2:
4836                 break;
4837         case RENDERPATH_GL11:
4838         case RENDERPATH_GL13:
4839         case RENDERPATH_GLES1:
4840                 wanttangents = false;
4841                 break;
4842         case RENDERPATH_SOFT:
4843                 break;
4844         }
4845
4846         if (r_shownormals.integer)
4847                 wanttangents = wantnormals = true;
4848
4849         // TODO: thread this
4850         // NOTE: R_PrepareRTLights() also caches entities
4851
4852         for (i = 0;i < r_refdef.scene.numentities;i++)
4853                 if (r_refdef.viewcache.entityvisible[i])
4854                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4855 }
4856
4857 //==================================================================================
4858
4859 extern cvar_t r_overheadsprites_pushback;
4860
4861 static void R_View_UpdateEntityLighting (void)
4862 {
4863         int i;
4864         entity_render_t *ent;
4865         vec3_t tempdiffusenormal, avg;
4866         vec_t f, fa, fd, fdd;
4867         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4868
4869         for (i = 0;i < r_refdef.scene.numentities;i++)
4870         {
4871                 ent = r_refdef.scene.entities[i];
4872
4873                 // skip unseen models
4874                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4875                         continue;
4876
4877                 // skip bsp models
4878                 if (ent->model && ent->model == cl.worldmodel)
4879                 {
4880                         // TODO: use modellight for r_ambient settings on world?
4881                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4882                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4883                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4884                         continue;
4885                 }
4886                 
4887                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4888                 {
4889                         // aleady updated by CSQC
4890                         // TODO: force modellight on BSP models in this case?
4891                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4892                 }
4893                 else
4894                 {
4895                         // fetch the lighting from the worldmodel data
4896                         VectorClear(ent->modellight_ambient);
4897                         VectorClear(ent->modellight_diffuse);
4898                         VectorClear(tempdiffusenormal);
4899                         if (ent->flags & RENDER_LIGHT)
4900                         {
4901                                 vec3_t org;
4902                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4903
4904                                 // complete lightning for lit sprites
4905                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4906                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4907                                 {
4908                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4909                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4910                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4911                                 }
4912                                 else
4913                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4914
4915                                 if(ent->flags & RENDER_EQUALIZE)
4916                                 {
4917                                         // first fix up ambient lighting...
4918                                         if(r_equalize_entities_minambient.value > 0)
4919                                         {
4920                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4921                                                 if(fd > 0)
4922                                                 {
4923                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4924                                                         if(fa < r_equalize_entities_minambient.value * fd)
4925                                                         {
4926                                                                 // solve:
4927                                                                 //   fa'/fd' = minambient
4928                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4929                                                                 //   ...
4930                                                                 //   fa' = fd' * minambient
4931                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4932                                                                 //   ...
4933                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4934                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4935                                                                 //   ...
4936                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4937                                                                 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
4938                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4939                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4940                                                         }
4941                                                 }
4942                                         }
4943
4944                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4945                                         {
4946                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4947                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4948                                                 f = fa + 0.25 * fd;
4949                                                 if(f > 0)
4950                                                 {
4951                                                         // adjust brightness and saturation to target
4952                                                         avg[0] = avg[1] = avg[2] = fa / f;
4953                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4954                                                         avg[0] = avg[1] = avg[2] = fd / f;
4955                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4956                                                 }
4957                                         }
4958                                 }
4959                         }
4960                         else // highly rare
4961                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4962                 }
4963
4964                 // move the light direction into modelspace coordinates for lighting code
4965                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4966                 if(VectorLength2(ent->modellight_lightdir) == 0)
4967                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4968                 VectorNormalize(ent->modellight_lightdir);
4969         }
4970 }
4971
4972 #define MAX_LINEOFSIGHTTRACES 64
4973
4974 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4975 {
4976         int i;
4977         vec3_t boxmins, boxmaxs;
4978         vec3_t start;
4979         vec3_t end;
4980         dp_model_t *model = r_refdef.scene.worldmodel;
4981
4982         if (!model || !model->brush.TraceLineOfSight)
4983                 return true;
4984
4985         // expand the box a little
4986         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4987         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4988         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4989         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4990         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4991         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4992
4993         // return true if eye is inside enlarged box
4994         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4995                 return true;
4996
4997         // try center
4998         VectorCopy(eye, start);
4999         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5000         if (model->brush.TraceLineOfSight(model, start, end))
5001                 return true;
5002
5003         // try various random positions
5004         for (i = 0;i < numsamples;i++)
5005         {
5006                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5007                 if (model->brush.TraceLineOfSight(model, start, end))
5008                         return true;
5009         }
5010
5011         return false;
5012 }
5013
5014
5015 static void R_View_UpdateEntityVisible (void)
5016 {
5017         int i;
5018         int renderimask;
5019         int samples;
5020         entity_render_t *ent;
5021
5022         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5023                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5024                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5025                 :                                                          RENDER_EXTERIORMODEL;
5026         if (!r_drawviewmodel.integer)
5027                 renderimask |= RENDER_VIEWMODEL;
5028         if (!r_drawexteriormodel.integer)
5029                 renderimask |= RENDER_EXTERIORMODEL;
5030         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5031         {
5032                 // worldmodel can check visibility
5033                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5034                 for (i = 0;i < r_refdef.scene.numentities;i++)
5035                 {
5036                         ent = r_refdef.scene.entities[i];
5037                         if (!(ent->flags & renderimask))
5038                         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)))
5039                         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))
5040                                 r_refdef.viewcache.entityvisible[i] = true;
5041                 }
5042         }
5043         else
5044         {
5045                 // no worldmodel or it can't check visibility
5046                 for (i = 0;i < r_refdef.scene.numentities;i++)
5047                 {
5048                         ent = r_refdef.scene.entities[i];
5049                         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));
5050                 }
5051         }
5052         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5053                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5054         {
5055                 for (i = 0;i < r_refdef.scene.numentities;i++)
5056                 {
5057                         if (!r_refdef.viewcache.entityvisible[i])
5058                                 continue;
5059                         ent = r_refdef.scene.entities[i];
5060                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5061                         {
5062                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5063                                 if (samples < 0)
5064                                         continue; // temp entities do pvs only
5065                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5066                                         ent->last_trace_visibility = realtime;
5067                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5068                                         r_refdef.viewcache.entityvisible[i] = 0;
5069                         }
5070                 }
5071         }
5072 }
5073
5074 /// only used if skyrendermasked, and normally returns false
5075 static int R_DrawBrushModelsSky (void)
5076 {
5077         int i, sky;
5078         entity_render_t *ent;
5079
5080         sky = false;
5081         for (i = 0;i < r_refdef.scene.numentities;i++)
5082         {
5083                 if (!r_refdef.viewcache.entityvisible[i])
5084                         continue;
5085                 ent = r_refdef.scene.entities[i];
5086                 if (!ent->model || !ent->model->DrawSky)
5087                         continue;
5088                 ent->model->DrawSky(ent);
5089                 sky = true;
5090         }
5091         return sky;
5092 }
5093
5094 static void R_DrawNoModel(entity_render_t *ent);
5095 static void R_DrawModels(void)
5096 {
5097         int i;
5098         entity_render_t *ent;
5099
5100         for (i = 0;i < r_refdef.scene.numentities;i++)
5101         {
5102                 if (!r_refdef.viewcache.entityvisible[i])
5103                         continue;
5104                 ent = r_refdef.scene.entities[i];
5105                 r_refdef.stats[r_stat_entities]++;
5106                 /*
5107                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5108                 {
5109                         vec3_t f, l, u, o;
5110                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5111                         Con_Printf("R_DrawModels\n");
5112                         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]);
5113                         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);
5114                         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);
5115                 }
5116                 */
5117                 if (ent->model && ent->model->Draw != NULL)
5118                         ent->model->Draw(ent);
5119                 else
5120                         R_DrawNoModel(ent);
5121         }
5122 }
5123
5124 static void R_DrawModelsDepth(void)
5125 {
5126         int i;
5127         entity_render_t *ent;
5128
5129         for (i = 0;i < r_refdef.scene.numentities;i++)
5130         {
5131                 if (!r_refdef.viewcache.entityvisible[i])
5132                         continue;
5133                 ent = r_refdef.scene.entities[i];
5134                 if (ent->model && ent->model->DrawDepth != NULL)
5135                         ent->model->DrawDepth(ent);
5136         }
5137 }
5138
5139 static void R_DrawModelsDebug(void)
5140 {
5141         int i;
5142         entity_render_t *ent;
5143
5144         for (i = 0;i < r_refdef.scene.numentities;i++)
5145         {
5146                 if (!r_refdef.viewcache.entityvisible[i])
5147                         continue;
5148                 ent = r_refdef.scene.entities[i];
5149                 if (ent->model && ent->model->DrawDebug != NULL)
5150                         ent->model->DrawDebug(ent);
5151         }
5152 }
5153
5154 static void R_DrawModelsAddWaterPlanes(void)
5155 {
5156         int i;
5157         entity_render_t *ent;
5158
5159         for (i = 0;i < r_refdef.scene.numentities;i++)
5160         {
5161                 if (!r_refdef.viewcache.entityvisible[i])
5162                         continue;
5163                 ent = r_refdef.scene.entities[i];
5164                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5165                         ent->model->DrawAddWaterPlanes(ent);
5166         }
5167 }
5168
5169 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}};
5170
5171 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5172 {
5173         if (r_hdr_irisadaptation.integer)
5174         {
5175                 vec3_t p;
5176                 vec3_t ambient;
5177                 vec3_t diffuse;
5178                 vec3_t diffusenormal;
5179                 vec3_t forward;
5180                 vec_t brightness = 0.0f;
5181                 vec_t goal;
5182                 vec_t current;
5183                 vec_t d;
5184                 int c;
5185                 VectorCopy(r_refdef.view.forward, forward);
5186                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5187                 {
5188                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5189                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5190                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5191                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5192                         d = DotProduct(forward, diffusenormal);
5193                         brightness += VectorLength(ambient);
5194                         if (d > 0)
5195                                 brightness += d * VectorLength(diffuse);
5196                 }
5197                 brightness *= 1.0f / c;
5198                 brightness += 0.00001f; // make sure it's never zero
5199                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5200                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5201                 current = r_hdr_irisadaptation_value.value;
5202                 if (current < goal)
5203                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5204                 else if (current > goal)
5205                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5206                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5207                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5208         }
5209         else if (r_hdr_irisadaptation_value.value != 1.0f)
5210                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5211 }
5212
5213 static void R_View_SetFrustum(const int *scissor)
5214 {
5215         int i;
5216         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5217         vec3_t forward, left, up, origin, v;
5218
5219         if(scissor)
5220         {
5221                 // flipped x coordinates (because x points left here)
5222                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5223                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5224
5225                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5226                 switch(vid.renderpath)
5227                 {
5228                         case RENDERPATH_D3D9:
5229                         case RENDERPATH_D3D10:
5230                         case RENDERPATH_D3D11:
5231                                 // non-flipped y coordinates
5232                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5233                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5234                                 break;
5235                         case RENDERPATH_SOFT:
5236                         case RENDERPATH_GL11:
5237                         case RENDERPATH_GL13:
5238                         case RENDERPATH_GL20:
5239                         case RENDERPATH_GLES1:
5240                         case RENDERPATH_GLES2:
5241                                 // non-flipped y coordinates
5242                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5243                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5244                                 break;
5245                 }
5246         }
5247
5248         // we can't trust r_refdef.view.forward and friends in reflected scenes
5249         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5250
5251 #if 0
5252         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5253         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5254         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5255         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5256         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5257         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5258         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5259         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5260         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5261         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5262         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5263         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5264 #endif
5265
5266 #if 0
5267         zNear = r_refdef.nearclip;
5268         nudge = 1.0 - 1.0 / (1<<23);
5269         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5270         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5271         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5272         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5273         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5274         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5275         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5276         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5277 #endif
5278
5279
5280
5281 #if 0
5282         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5283         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5284         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5285         r_refdef.view.frustum[0].dist = m[15] - m[12];
5286
5287         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5288         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5289         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5290         r_refdef.view.frustum[1].dist = m[15] + m[12];
5291
5292         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5293         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5294         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5295         r_refdef.view.frustum[2].dist = m[15] - m[13];
5296
5297         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5298         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5299         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5300         r_refdef.view.frustum[3].dist = m[15] + m[13];
5301
5302         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5303         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5304         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5305         r_refdef.view.frustum[4].dist = m[15] - m[14];
5306
5307         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5308         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5309         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5310         r_refdef.view.frustum[5].dist = m[15] + m[14];
5311 #endif
5312
5313         if (r_refdef.view.useperspective)
5314         {
5315                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5316                 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]);
5317                 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]);
5318                 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]);
5319                 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]);
5320
5321                 // then the normals from the corners relative to origin
5322                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5323                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5324                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5325                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5326
5327                 // in a NORMAL view, forward cross left == up
5328                 // in a REFLECTED view, forward cross left == down
5329                 // so our cross products above need to be adjusted for a left handed coordinate system
5330                 CrossProduct(forward, left, v);
5331                 if(DotProduct(v, up) < 0)
5332                 {
5333                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5334                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5335                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5336                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5337                 }
5338
5339                 // Leaving those out was a mistake, those were in the old code, and they
5340                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5341                 // I couldn't reproduce it after adding those normalizations. --blub
5342                 VectorNormalize(r_refdef.view.frustum[0].normal);
5343                 VectorNormalize(r_refdef.view.frustum[1].normal);
5344                 VectorNormalize(r_refdef.view.frustum[2].normal);
5345                 VectorNormalize(r_refdef.view.frustum[3].normal);
5346
5347                 // make the corners absolute
5348                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5349                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5350                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5351                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5352
5353                 // one more normal
5354                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5355
5356                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5357                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5358                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5359                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5360                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5361         }
5362         else
5363         {
5364                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5365                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5366                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5367                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5368                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5369                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5370                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5371                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5372                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5373                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5374         }
5375         r_refdef.view.numfrustumplanes = 5;
5376
5377         if (r_refdef.view.useclipplane)
5378         {
5379                 r_refdef.view.numfrustumplanes = 6;
5380                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5381         }
5382
5383         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5384                 PlaneClassify(r_refdef.view.frustum + i);
5385
5386         // LordHavoc: note to all quake engine coders, Quake had a special case
5387         // for 90 degrees which assumed a square view (wrong), so I removed it,
5388         // Quake2 has it disabled as well.
5389
5390         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5391         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5392         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5393         //PlaneClassify(&frustum[0]);
5394
5395         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5396         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5397         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5398         //PlaneClassify(&frustum[1]);
5399
5400         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5401         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5402         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5403         //PlaneClassify(&frustum[2]);
5404
5405         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5406         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5407         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5408         //PlaneClassify(&frustum[3]);
5409
5410         // nearclip plane
5411         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5412         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5413         //PlaneClassify(&frustum[4]);
5414 }
5415
5416 static void R_View_UpdateWithScissor(const int *myscissor)
5417 {
5418         R_Main_ResizeViewCache();
5419         R_View_SetFrustum(myscissor);
5420         R_View_WorldVisibility(r_refdef.view.useclipplane);
5421         R_View_UpdateEntityVisible();
5422         R_View_UpdateEntityLighting();
5423 }
5424
5425 static void R_View_Update(void)
5426 {
5427         R_Main_ResizeViewCache();
5428         R_View_SetFrustum(NULL);
5429         R_View_WorldVisibility(r_refdef.view.useclipplane);
5430         R_View_UpdateEntityVisible();
5431         R_View_UpdateEntityLighting();
5432 }
5433
5434 float viewscalefpsadjusted = 1.0f;
5435
5436 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5437 {
5438         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5439         scale = bound(0.03125f, scale, 1.0f);
5440         *outwidth = (int)ceil(width * scale);
5441         *outheight = (int)ceil(height * scale);
5442 }
5443
5444 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5445 {
5446         const float *customclipplane = NULL;
5447         float plane[4];
5448         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5449         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5450         {
5451                 // LordHavoc: couldn't figure out how to make this approach the
5452                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5453                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5454                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5455                         dist = r_refdef.view.clipplane.dist;
5456                 plane[0] = r_refdef.view.clipplane.normal[0];
5457                 plane[1] = r_refdef.view.clipplane.normal[1];
5458                 plane[2] = r_refdef.view.clipplane.normal[2];
5459                 plane[3] = -dist;
5460                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5461         }
5462
5463         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5464         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5465
5466         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5467         if (!r_refdef.view.useperspective)
5468                 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);
5469         else if (vid.stencil && r_useinfinitefarclip.integer)
5470                 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);
5471         else
5472                 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);
5473         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5474         R_SetViewport(&r_refdef.view.viewport);
5475         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5476         {
5477                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5478                 float screenplane[4];
5479                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5480                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5481                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5482                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5483                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5484         }
5485 }
5486
5487 void R_EntityMatrix(const matrix4x4_t *matrix)
5488 {
5489         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5490         {
5491                 gl_modelmatrixchanged = false;
5492                 gl_modelmatrix = *matrix;
5493                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5494                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5495                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5496                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5497                 CHECKGLERROR
5498                 switch(vid.renderpath)
5499                 {
5500                 case RENDERPATH_D3D9:
5501 #ifdef SUPPORTD3D
5502                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5503                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5504 #endif
5505                         break;
5506                 case RENDERPATH_D3D10:
5507                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5508                         break;
5509                 case RENDERPATH_D3D11:
5510                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5511                         break;
5512                 case RENDERPATH_GL11:
5513                 case RENDERPATH_GL13:
5514                 case RENDERPATH_GLES1:
5515                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5516                         break;
5517                 case RENDERPATH_SOFT:
5518                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5519                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5520                         break;
5521                 case RENDERPATH_GL20:
5522                 case RENDERPATH_GLES2:
5523                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5524                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5525                         break;
5526                 }
5527         }
5528 }
5529
5530 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5531 {
5532         r_viewport_t viewport;
5533
5534         CHECKGLERROR
5535
5536         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5537         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);
5538         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5539         R_SetViewport(&viewport);
5540         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5541         GL_Color(1, 1, 1, 1);
5542         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5543         GL_BlendFunc(GL_ONE, GL_ZERO);
5544         GL_ScissorTest(false);
5545         GL_DepthMask(false);
5546         GL_DepthRange(0, 1);
5547         GL_DepthTest(false);
5548         GL_DepthFunc(GL_LEQUAL);
5549         R_EntityMatrix(&identitymatrix);
5550         R_Mesh_ResetTextureState();
5551         GL_PolygonOffset(0, 0);
5552         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5553         switch(vid.renderpath)
5554         {
5555         case RENDERPATH_GL11:
5556         case RENDERPATH_GL13:
5557         case RENDERPATH_GL20:
5558         case RENDERPATH_GLES1:
5559         case RENDERPATH_GLES2:
5560                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5561                 break;
5562         case RENDERPATH_D3D9:
5563         case RENDERPATH_D3D10:
5564         case RENDERPATH_D3D11:
5565         case RENDERPATH_SOFT:
5566                 break;
5567         }
5568         GL_CullFace(GL_NONE);
5569
5570         CHECKGLERROR
5571 }
5572
5573 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5574 {
5575         DrawQ_Finish();
5576
5577         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5578 }
5579
5580 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5581 {
5582         DrawQ_Finish();
5583
5584         R_SetupView(true, fbo, depthtexture, colortexture);
5585         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5586         GL_Color(1, 1, 1, 1);
5587         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5588         GL_BlendFunc(GL_ONE, GL_ZERO);
5589         GL_ScissorTest(true);
5590         GL_DepthMask(true);
5591         GL_DepthRange(0, 1);
5592         GL_DepthTest(true);
5593         GL_DepthFunc(GL_LEQUAL);
5594         R_EntityMatrix(&identitymatrix);
5595         R_Mesh_ResetTextureState();
5596         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5597         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5598         switch(vid.renderpath)
5599         {
5600         case RENDERPATH_GL11:
5601         case RENDERPATH_GL13:
5602         case RENDERPATH_GL20:
5603         case RENDERPATH_GLES1:
5604         case RENDERPATH_GLES2:
5605                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5606                 break;
5607         case RENDERPATH_D3D9:
5608         case RENDERPATH_D3D10:
5609         case RENDERPATH_D3D11:
5610         case RENDERPATH_SOFT:
5611                 break;
5612         }
5613         GL_CullFace(r_refdef.view.cullface_back);
5614 }
5615
5616 /*
5617 ================
5618 R_RenderView_UpdateViewVectors
5619 ================
5620 */
5621 void R_RenderView_UpdateViewVectors(void)
5622 {
5623         // break apart the view matrix into vectors for various purposes
5624         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5625         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5626         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5627         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5628         // make an inverted copy of the view matrix for tracking sprites
5629         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5630 }
5631
5632 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5633 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5634
5635 static void R_Water_StartFrame(void)
5636 {
5637         int i;
5638         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5639         r_waterstate_waterplane_t *p;
5640         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;
5641
5642         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5643                 return;
5644
5645         switch(vid.renderpath)
5646         {
5647         case RENDERPATH_GL20:
5648         case RENDERPATH_D3D9:
5649         case RENDERPATH_D3D10:
5650         case RENDERPATH_D3D11:
5651         case RENDERPATH_SOFT:
5652         case RENDERPATH_GLES2:
5653                 break;
5654         case RENDERPATH_GL11:
5655         case RENDERPATH_GL13:
5656         case RENDERPATH_GLES1:
5657                 return;
5658         }
5659
5660         // set waterwidth and waterheight to the water resolution that will be
5661         // used (often less than the screen resolution for faster rendering)
5662         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5663
5664         // calculate desired texture sizes
5665         // can't use water if the card does not support the texture size
5666         if (!r_water.integer || r_showsurfaces.integer)
5667                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5668         else if (vid.support.arb_texture_non_power_of_two)
5669         {
5670                 texturewidth = waterwidth;
5671                 textureheight = waterheight;
5672                 camerawidth = waterwidth;
5673                 cameraheight = waterheight;
5674         }
5675         else
5676         {
5677                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5678                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5679                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5680                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5681         }
5682
5683         // allocate textures as needed
5684         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))
5685         {
5686                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5687                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5688                 {
5689                         if (p->texture_refraction)
5690                                 R_FreeTexture(p->texture_refraction);
5691                         p->texture_refraction = NULL;
5692                         if (p->fbo_refraction)
5693                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5694                         p->fbo_refraction = 0;
5695                         if (p->texture_reflection)
5696                                 R_FreeTexture(p->texture_reflection);
5697                         p->texture_reflection = NULL;
5698                         if (p->fbo_reflection)
5699                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5700                         p->fbo_reflection = 0;
5701                         if (p->texture_camera)
5702                                 R_FreeTexture(p->texture_camera);
5703                         p->texture_camera = NULL;
5704                         if (p->fbo_camera)
5705                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5706                         p->fbo_camera = 0;
5707                 }
5708                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5709                 r_fb.water.texturewidth = texturewidth;
5710                 r_fb.water.textureheight = textureheight;
5711                 r_fb.water.camerawidth = camerawidth;
5712                 r_fb.water.cameraheight = cameraheight;
5713         }
5714
5715         if (r_fb.water.texturewidth)
5716         {
5717                 int scaledwidth, scaledheight;
5718
5719                 r_fb.water.enabled = true;
5720
5721                 // water resolution is usually reduced
5722                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5723                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5724                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5725
5726                 // set up variables that will be used in shader setup
5727                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5728                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5729                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5730                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5731         }
5732
5733         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5734         r_fb.water.numwaterplanes = 0;
5735 }
5736
5737 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5738 {
5739         int planeindex, bestplaneindex, vertexindex;
5740         vec3_t mins, maxs, normal, center, v, n;
5741         vec_t planescore, bestplanescore;
5742         mplane_t plane;
5743         r_waterstate_waterplane_t *p;
5744         texture_t *t = R_GetCurrentTexture(surface->texture);
5745
5746         rsurface.texture = t;
5747         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5748         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5749         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5750                 return;
5751         // average the vertex normals, find the surface bounds (after deformvertexes)
5752         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5753         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5754         VectorCopy(n, normal);
5755         VectorCopy(v, mins);
5756         VectorCopy(v, maxs);
5757         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5758         {
5759                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5760                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5761                 VectorAdd(normal, n, normal);
5762                 mins[0] = min(mins[0], v[0]);
5763                 mins[1] = min(mins[1], v[1]);
5764                 mins[2] = min(mins[2], v[2]);
5765                 maxs[0] = max(maxs[0], v[0]);
5766                 maxs[1] = max(maxs[1], v[1]);
5767                 maxs[2] = max(maxs[2], v[2]);
5768         }
5769         VectorNormalize(normal);
5770         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5771
5772         VectorCopy(normal, plane.normal);
5773         VectorNormalize(plane.normal);
5774         plane.dist = DotProduct(center, plane.normal);
5775         PlaneClassify(&plane);
5776         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5777         {
5778                 // skip backfaces (except if nocullface is set)
5779 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5780 //                      return;
5781                 VectorNegate(plane.normal, plane.normal);
5782                 plane.dist *= -1;
5783                 PlaneClassify(&plane);
5784         }
5785
5786
5787         // find a matching plane if there is one
5788         bestplaneindex = -1;
5789         bestplanescore = 1048576.0f;
5790         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5791         {
5792                 if(p->camera_entity == t->camera_entity)
5793                 {
5794                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5795                         if (bestplaneindex < 0 || bestplanescore > planescore)
5796                         {
5797                                 bestplaneindex = planeindex;
5798                                 bestplanescore = planescore;
5799                         }
5800                 }
5801         }
5802         planeindex = bestplaneindex;
5803         p = r_fb.water.waterplanes + planeindex;
5804
5805         // if this surface does not fit any known plane rendered this frame, add one
5806         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5807         {
5808                 // store the new plane
5809                 planeindex = r_fb.water.numwaterplanes++;
5810                 p = r_fb.water.waterplanes + planeindex;
5811                 p->plane = plane;
5812                 // clear materialflags and pvs
5813                 p->materialflags = 0;
5814                 p->pvsvalid = false;
5815                 p->camera_entity = t->camera_entity;
5816                 VectorCopy(mins, p->mins);
5817                 VectorCopy(maxs, p->maxs);
5818         }
5819         else
5820         {
5821                 // merge mins/maxs when we're adding this surface to the plane
5822                 p->mins[0] = min(p->mins[0], mins[0]);
5823                 p->mins[1] = min(p->mins[1], mins[1]);
5824                 p->mins[2] = min(p->mins[2], mins[2]);
5825                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5826                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5827                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5828         }
5829         // merge this surface's materialflags into the waterplane
5830         p->materialflags |= t->currentmaterialflags;
5831         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5832         {
5833                 // merge this surface's PVS into the waterplane
5834                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5835                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5836                 {
5837                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5838                         p->pvsvalid = true;
5839                 }
5840         }
5841 }
5842
5843 extern cvar_t r_drawparticles;
5844 extern cvar_t r_drawdecals;
5845
5846 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5847 {
5848         int myscissor[4];
5849         r_refdef_view_t originalview;
5850         r_refdef_view_t myview;
5851         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;
5852         r_waterstate_waterplane_t *p;
5853         vec3_t visorigin;
5854         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;
5855         char vabuf[1024];
5856
5857         originalview = r_refdef.view;
5858
5859         // lowquality hack, temporarily shut down some cvars and restore afterwards
5860         qualityreduction = r_water_lowquality.integer;
5861         if (qualityreduction > 0)
5862         {
5863                 if (qualityreduction >= 1)
5864                 {
5865                         old_r_shadows = r_shadows.integer;
5866                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5867                         old_r_dlight = r_shadow_realtime_dlight.integer;
5868                         Cvar_SetValueQuick(&r_shadows, 0);
5869                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5870                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5871                 }
5872                 if (qualityreduction >= 2)
5873                 {
5874                         old_r_dynamic = r_dynamic.integer;
5875                         old_r_particles = r_drawparticles.integer;
5876                         old_r_decals = r_drawdecals.integer;
5877                         Cvar_SetValueQuick(&r_dynamic, 0);
5878                         Cvar_SetValueQuick(&r_drawparticles, 0);
5879                         Cvar_SetValueQuick(&r_drawdecals, 0);
5880                 }
5881         }
5882
5883         // make sure enough textures are allocated
5884         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5885         {
5886                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5887                 {
5888                         if (!p->texture_refraction)
5889                                 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);
5890                         if (!p->texture_refraction)
5891                                 goto error;
5892                         if (usewaterfbo)
5893                         {
5894                                 if (r_fb.water.depthtexture == NULL)
5895                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5896                                 if (p->fbo_refraction == 0)
5897                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5898                         }
5899                 }
5900                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5901                 {
5902                         if (!p->texture_camera)
5903                                 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);
5904                         if (!p->texture_camera)
5905                                 goto error;
5906                         if (usewaterfbo)
5907                         {
5908                                 if (r_fb.water.depthtexture == NULL)
5909                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5910                                 if (p->fbo_camera == 0)
5911                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5912                         }
5913                 }
5914
5915                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5916                 {
5917                         if (!p->texture_reflection)
5918                                 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);
5919                         if (!p->texture_reflection)
5920                                 goto error;
5921                         if (usewaterfbo)
5922                         {
5923                                 if (r_fb.water.depthtexture == NULL)
5924                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5925                                 if (p->fbo_reflection == 0)
5926                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5927                         }
5928                 }
5929         }
5930
5931         // render views
5932         r_refdef.view = originalview;
5933         r_refdef.view.showdebug = false;
5934         r_refdef.view.width = r_fb.water.waterwidth;
5935         r_refdef.view.height = r_fb.water.waterheight;
5936         r_refdef.view.useclipplane = true;
5937         myview = r_refdef.view;
5938         r_fb.water.renderingscene = true;
5939         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5940         {
5941                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5942                 {
5943                         r_refdef.view = myview;
5944                         if(r_water_scissormode.integer)
5945                         {
5946                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5947                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5948                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5949                         }
5950
5951                         // render reflected scene and copy into texture
5952                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5953                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5954                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5955                         r_refdef.view.clipplane = p->plane;
5956                         // reverse the cullface settings for this render
5957                         r_refdef.view.cullface_front = GL_FRONT;
5958                         r_refdef.view.cullface_back = GL_BACK;
5959                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5960                         {
5961                                 r_refdef.view.usecustompvs = true;
5962                                 if (p->pvsvalid)
5963                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5964                                 else
5965                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5966                         }
5967
5968                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5969                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5970                         R_ClearScreen(r_refdef.fogenabled);
5971                         if(r_water_scissormode.integer & 2)
5972                                 R_View_UpdateWithScissor(myscissor);
5973                         else
5974                                 R_View_Update();
5975                         R_AnimCache_CacheVisibleEntities();
5976                         if(r_water_scissormode.integer & 1)
5977                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5978                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5979
5980                         if (!p->fbo_reflection)
5981                                 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);
5982                         r_fb.water.hideplayer = false;
5983                 }
5984
5985                 // render the normal view scene and copy into texture
5986                 // (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)
5987                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5988                 {
5989                         r_refdef.view = myview;
5990                         if(r_water_scissormode.integer)
5991                         {
5992                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5993                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5994                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5995                         }
5996
5997                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5998
5999                         r_refdef.view.clipplane = p->plane;
6000                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6001                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6002
6003                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6004                         {
6005                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6006                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6007                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6008                                 R_RenderView_UpdateViewVectors();
6009                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6010                                 {
6011                                         r_refdef.view.usecustompvs = true;
6012                                         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);
6013                                 }
6014                         }
6015
6016                         PlaneClassify(&r_refdef.view.clipplane);
6017
6018                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6019                         R_ClearScreen(r_refdef.fogenabled);
6020                         if(r_water_scissormode.integer & 2)
6021                                 R_View_UpdateWithScissor(myscissor);
6022                         else
6023                                 R_View_Update();
6024                         R_AnimCache_CacheVisibleEntities();
6025                         if(r_water_scissormode.integer & 1)
6026                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6027                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6028
6029                         if (!p->fbo_refraction)
6030                                 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);
6031                         r_fb.water.hideplayer = false;
6032                 }
6033                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6034                 {
6035                         r_refdef.view = myview;
6036
6037                         r_refdef.view.clipplane = p->plane;
6038                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6039                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6040
6041                         r_refdef.view.width = r_fb.water.camerawidth;
6042                         r_refdef.view.height = r_fb.water.cameraheight;
6043                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6044                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6045                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6046                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6047
6048                         if(p->camera_entity)
6049                         {
6050                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6051                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6052                         }
6053
6054                         // note: all of the view is used for displaying... so
6055                         // there is no use in scissoring
6056
6057                         // reverse the cullface settings for this render
6058                         r_refdef.view.cullface_front = GL_FRONT;
6059                         r_refdef.view.cullface_back = GL_BACK;
6060                         // also reverse the view matrix
6061                         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
6062                         R_RenderView_UpdateViewVectors();
6063                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6064                         {
6065                                 r_refdef.view.usecustompvs = true;
6066                                 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);
6067                         }
6068                         
6069                         // camera needs no clipplane
6070                         r_refdef.view.useclipplane = false;
6071
6072                         PlaneClassify(&r_refdef.view.clipplane);
6073
6074                         r_fb.water.hideplayer = false;
6075
6076                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6077                         R_ClearScreen(r_refdef.fogenabled);
6078                         R_View_Update();
6079                         R_AnimCache_CacheVisibleEntities();
6080                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6081
6082                         if (!p->fbo_camera)
6083                                 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);
6084                         r_fb.water.hideplayer = false;
6085                 }
6086
6087         }
6088         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6089         r_fb.water.renderingscene = false;
6090         r_refdef.view = originalview;
6091         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6092         if (!r_fb.water.depthtexture)
6093                 R_ClearScreen(r_refdef.fogenabled);
6094         R_View_Update();
6095         R_AnimCache_CacheVisibleEntities();
6096         goto finish;
6097 error:
6098         r_refdef.view = originalview;
6099         r_fb.water.renderingscene = false;
6100         Cvar_SetValueQuick(&r_water, 0);
6101         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6102 finish:
6103         // lowquality hack, restore cvars
6104         if (qualityreduction > 0)
6105         {
6106                 if (qualityreduction >= 1)
6107                 {
6108                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6109                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6110                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6111                 }
6112                 if (qualityreduction >= 2)
6113                 {
6114                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6115                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6116                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6117                 }
6118         }
6119 }
6120
6121 static void R_Bloom_StartFrame(void)
6122 {
6123         int i;
6124         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6125         int viewwidth, viewheight;
6126         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6127         textype_t textype = TEXTYPE_COLORBUFFER;
6128
6129         switch (vid.renderpath)
6130         {
6131         case RENDERPATH_GL20:
6132                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6133                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6134                 {
6135                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6136                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6137                 }
6138                 break;
6139         case RENDERPATH_GL11:
6140         case RENDERPATH_GL13:
6141         case RENDERPATH_GLES1:
6142         case RENDERPATH_GLES2:
6143         case RENDERPATH_D3D9:
6144         case RENDERPATH_D3D10:
6145         case RENDERPATH_D3D11:
6146                 r_fb.usedepthtextures = false;
6147                 break;
6148         case RENDERPATH_SOFT:
6149                 r_fb.usedepthtextures = true;
6150                 break;
6151         }
6152
6153         if (r_viewscale_fpsscaling.integer)
6154         {
6155                 double actualframetime;
6156                 double targetframetime;
6157                 double adjust;
6158                 actualframetime = r_refdef.lastdrawscreentime;
6159                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6160                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6161                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6162                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6163                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6164                 viewscalefpsadjusted += adjust;
6165                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6166         }
6167         else
6168                 viewscalefpsadjusted = 1.0f;
6169
6170         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6171
6172         switch(vid.renderpath)
6173         {
6174         case RENDERPATH_GL20:
6175         case RENDERPATH_D3D9:
6176         case RENDERPATH_D3D10:
6177         case RENDERPATH_D3D11:
6178         case RENDERPATH_SOFT:
6179         case RENDERPATH_GLES2:
6180                 break;
6181         case RENDERPATH_GL11:
6182         case RENDERPATH_GL13:
6183         case RENDERPATH_GLES1:
6184                 return;
6185         }
6186
6187         // set bloomwidth and bloomheight to the bloom resolution that will be
6188         // used (often less than the screen resolution for faster rendering)
6189         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6190         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6191         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6192         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6193         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6194
6195         // calculate desired texture sizes
6196         if (vid.support.arb_texture_non_power_of_two)
6197         {
6198                 screentexturewidth = vid.width;
6199                 screentextureheight = vid.height;
6200                 bloomtexturewidth = r_fb.bloomwidth;
6201                 bloomtextureheight = r_fb.bloomheight;
6202         }
6203         else
6204         {
6205                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6206                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6207                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6208                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6209         }
6210
6211         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))
6212         {
6213                 Cvar_SetValueQuick(&r_bloom, 0);
6214                 Cvar_SetValueQuick(&r_motionblur, 0);
6215                 Cvar_SetValueQuick(&r_damageblur, 0);
6216         }
6217
6218         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6219          && !r_bloom.integer
6220          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6221          && !useviewfbo
6222          && r_viewscale.value == 1.0f
6223          && !r_viewscale_fpsscaling.integer)
6224                 screentexturewidth = screentextureheight = 0;
6225         if (!r_bloom.integer)
6226                 bloomtexturewidth = bloomtextureheight = 0;
6227
6228         // allocate textures as needed
6229         if (r_fb.screentexturewidth != screentexturewidth
6230          || r_fb.screentextureheight != screentextureheight
6231          || r_fb.bloomtexturewidth != bloomtexturewidth
6232          || r_fb.bloomtextureheight != bloomtextureheight
6233          || r_fb.textype != textype
6234          || useviewfbo != (r_fb.fbo != 0))
6235         {
6236                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6237                 {
6238                         if (r_fb.bloomtexture[i])
6239                                 R_FreeTexture(r_fb.bloomtexture[i]);
6240                         r_fb.bloomtexture[i] = NULL;
6241
6242                         if (r_fb.bloomfbo[i])
6243                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6244                         r_fb.bloomfbo[i] = 0;
6245                 }
6246
6247                 if (r_fb.fbo)
6248                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6249                 r_fb.fbo = 0;
6250
6251                 if (r_fb.colortexture)
6252                         R_FreeTexture(r_fb.colortexture);
6253                 r_fb.colortexture = NULL;
6254
6255                 if (r_fb.depthtexture)
6256                         R_FreeTexture(r_fb.depthtexture);
6257                 r_fb.depthtexture = NULL;
6258
6259                 if (r_fb.ghosttexture)
6260                         R_FreeTexture(r_fb.ghosttexture);
6261                 r_fb.ghosttexture = NULL;
6262
6263                 r_fb.screentexturewidth = screentexturewidth;
6264                 r_fb.screentextureheight = screentextureheight;
6265                 r_fb.bloomtexturewidth = bloomtexturewidth;
6266                 r_fb.bloomtextureheight = bloomtextureheight;
6267                 r_fb.textype = textype;
6268
6269                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6270                 {
6271                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6272                                 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);
6273                         r_fb.ghosttexture_valid = false;
6274                         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);
6275                         if (useviewfbo)
6276                         {
6277                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6278                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6279                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6280                         }
6281                 }
6282
6283                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6284                 {
6285                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6286                         {
6287                                 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);
6288                                 if (useviewfbo)
6289                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6290                         }
6291                 }
6292         }
6293
6294         // bloom texture is a different resolution
6295         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6296         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6297         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6298         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6299         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6300
6301         // set up a texcoord array for the full resolution screen image
6302         // (we have to keep this around to copy back during final render)
6303         r_fb.screentexcoord2f[0] = 0;
6304         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6305         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6306         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6307         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6308         r_fb.screentexcoord2f[5] = 0;
6309         r_fb.screentexcoord2f[6] = 0;
6310         r_fb.screentexcoord2f[7] = 0;
6311
6312         if(r_fb.fbo) 
6313         {
6314                 for (i = 1;i < 8;i += 2)
6315                 {
6316                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6317                 }
6318         }
6319
6320         // set up a texcoord array for the reduced resolution bloom image
6321         // (which will be additive blended over the screen image)
6322         r_fb.bloomtexcoord2f[0] = 0;
6323         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6324         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6325         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6326         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6327         r_fb.bloomtexcoord2f[5] = 0;
6328         r_fb.bloomtexcoord2f[6] = 0;
6329         r_fb.bloomtexcoord2f[7] = 0;
6330
6331         switch(vid.renderpath)
6332         {
6333         case RENDERPATH_GL11:
6334         case RENDERPATH_GL13:
6335         case RENDERPATH_GL20:
6336         case RENDERPATH_SOFT:
6337         case RENDERPATH_GLES1:
6338         case RENDERPATH_GLES2:
6339                 break;
6340         case RENDERPATH_D3D9:
6341         case RENDERPATH_D3D10:
6342         case RENDERPATH_D3D11:
6343                 for (i = 0;i < 4;i++)
6344                 {
6345                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6346                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6347                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6348                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6349                 }
6350                 break;
6351         }
6352
6353         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6354
6355         if (r_fb.fbo)
6356                 r_refdef.view.clear = true;
6357 }
6358
6359 static void R_Bloom_MakeTexture(void)
6360 {
6361         int x, range, dir;
6362         float xoffset, yoffset, r, brighten;
6363         rtexture_t *intex;
6364         float colorscale = r_bloom_colorscale.value;
6365
6366         r_refdef.stats[r_stat_bloom]++;
6367     
6368 #if 0
6369     // this copy is unnecessary since it happens in R_BlendView already
6370         if (!r_fb.fbo)
6371         {
6372                 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);
6373                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6374         }
6375 #endif
6376
6377         // scale down screen texture to the bloom texture size
6378         CHECKGLERROR
6379         r_fb.bloomindex = 0;
6380         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6381         R_SetViewport(&r_fb.bloomviewport);
6382         GL_DepthTest(false);
6383         GL_BlendFunc(GL_ONE, GL_ZERO);
6384         GL_Color(colorscale, colorscale, colorscale, 1);
6385         // 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...
6386         switch(vid.renderpath)
6387         {
6388         case RENDERPATH_GL11:
6389         case RENDERPATH_GL13:
6390         case RENDERPATH_GL20:
6391         case RENDERPATH_GLES1:
6392         case RENDERPATH_GLES2:
6393         case RENDERPATH_SOFT:
6394                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6395                 break;
6396         case RENDERPATH_D3D9:
6397         case RENDERPATH_D3D10:
6398         case RENDERPATH_D3D11:
6399                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6400                 break;
6401         }
6402         // TODO: do boxfilter scale-down in shader?
6403         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6404         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6405         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6406
6407         // we now have a properly scaled bloom image
6408         if (!r_fb.bloomfbo[r_fb.bloomindex])
6409         {
6410                 // copy it into the bloom texture
6411                 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);
6412                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6413         }
6414
6415         // multiply bloom image by itself as many times as desired
6416         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6417         {
6418                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6419                 r_fb.bloomindex ^= 1;
6420                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6421                 x *= 2;
6422                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6423                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6424                 {
6425                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6426                         GL_Color(r,r,r,1); // apply fix factor
6427                 }
6428                 else
6429                 {
6430                         if(x <= 2)
6431                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6432                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6433                         GL_Color(1,1,1,1); // no fix factor supported here
6434                 }
6435                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6436                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6437                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6438                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6439
6440                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6441                 {
6442                         // copy the darkened image to a texture
6443                         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);
6444                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6445                 }
6446         }
6447
6448         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6449         brighten = r_bloom_brighten.value;
6450         brighten = sqrt(brighten);
6451         if(range >= 1)
6452                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6453
6454         for (dir = 0;dir < 2;dir++)
6455         {
6456                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6457                 r_fb.bloomindex ^= 1;
6458                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6459                 // blend on at multiple vertical offsets to achieve a vertical blur
6460                 // TODO: do offset blends using GLSL
6461                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6462                 GL_BlendFunc(GL_ONE, GL_ZERO);
6463                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6464                 for (x = -range;x <= range;x++)
6465                 {
6466                         if (!dir){xoffset = 0;yoffset = x;}
6467                         else {xoffset = x;yoffset = 0;}
6468                         xoffset /= (float)r_fb.bloomtexturewidth;
6469                         yoffset /= (float)r_fb.bloomtextureheight;
6470                         // compute a texcoord array with the specified x and y offset
6471                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6472                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6473                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6474                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6475                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6476                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6477                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6478                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6479                         // this r value looks like a 'dot' particle, fading sharply to
6480                         // black at the edges
6481                         // (probably not realistic but looks good enough)
6482                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6483                         //r = brighten/(range*2+1);
6484                         r = brighten / (range * 2 + 1);
6485                         if(range >= 1)
6486                                 r *= (1 - x*x/(float)(range*range));
6487                         GL_Color(r, r, r, 1);
6488                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6489                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6490                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6491                         GL_BlendFunc(GL_ONE, GL_ONE);
6492                 }
6493
6494                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6495                 {
6496                         // copy the vertically or horizontally blurred bloom view to a texture
6497                         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);
6498                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6499                 }
6500         }
6501 }
6502
6503 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6504 {
6505         unsigned int permutation;
6506         float uservecs[4][4];
6507
6508         R_EntityMatrix(&identitymatrix);
6509
6510         switch (vid.renderpath)
6511         {
6512         case RENDERPATH_GL20:
6513         case RENDERPATH_D3D9:
6514         case RENDERPATH_D3D10:
6515         case RENDERPATH_D3D11:
6516         case RENDERPATH_SOFT:
6517         case RENDERPATH_GLES2:
6518                 permutation =
6519                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6520                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6521                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6522                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6523                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6524
6525                 if (r_fb.colortexture)
6526                 {
6527                         if (!r_fb.fbo)
6528                         {
6529                                 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);
6530                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6531                         }
6532
6533                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6534                         {
6535                                 // declare variables
6536                                 float blur_factor, blur_mouseaccel, blur_velocity;
6537                                 static float blur_average; 
6538                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6539
6540                                 // set a goal for the factoring
6541                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6542                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6543                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6544                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6545                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6546                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6547
6548                                 // from the goal, pick an averaged value between goal and last value
6549                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6550                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6551
6552                                 // enforce minimum amount of blur 
6553                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6554
6555                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6556
6557                                 // calculate values into a standard alpha
6558                                 cl.motionbluralpha = 1 - exp(-
6559                                                 (
6560                                                  (r_motionblur.value * blur_factor / 80)
6561                                                  +
6562                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6563                                                 )
6564                                                 /
6565                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6566                                           );
6567
6568                                 // randomization for the blur value to combat persistent ghosting
6569                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6570                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6571
6572                                 // apply the blur
6573                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6574                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6575                                 {
6576                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6577                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6578                                         switch(vid.renderpath)
6579                                         {
6580                                         case RENDERPATH_GL11:
6581                                         case RENDERPATH_GL13:
6582                                         case RENDERPATH_GL20:
6583                                         case RENDERPATH_GLES1:
6584                                         case RENDERPATH_GLES2:
6585                                         case RENDERPATH_SOFT:
6586                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6587                                                 break;
6588                                         case RENDERPATH_D3D9:
6589                                         case RENDERPATH_D3D10:
6590                                         case RENDERPATH_D3D11:
6591                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6592                                                 break;
6593                                         }
6594                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6595                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6596                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6597                                 }
6598
6599                                 // updates old view angles for next pass
6600                                 VectorCopy(cl.viewangles, blur_oldangles);
6601
6602                                 // copy view into the ghost texture
6603                                 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);
6604                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6605                                 r_fb.ghosttexture_valid = true;
6606                         }
6607                 }
6608                 else
6609                 {
6610                         // no r_fb.colortexture means we're rendering to the real fb
6611                         // we may still have to do view tint...
6612                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6613                         {
6614                                 // apply a color tint to the whole view
6615                                 R_ResetViewRendering2D(0, NULL, NULL);
6616                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6617                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6618                                 R_SetupShader_Generic_NoTexture(false, true);
6619                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6620                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6621                         }
6622                         break; // no screen processing, no bloom, skip it
6623                 }
6624
6625                 if (r_fb.bloomtexture[0])
6626                 {
6627                         // make the bloom texture
6628                         R_Bloom_MakeTexture();
6629                 }
6630
6631 #if _MSC_VER >= 1400
6632 #define sscanf sscanf_s
6633 #endif
6634                 memset(uservecs, 0, sizeof(uservecs));
6635                 if (r_glsl_postprocess_uservec1_enable.integer)
6636                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6637                 if (r_glsl_postprocess_uservec2_enable.integer)
6638                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6639                 if (r_glsl_postprocess_uservec3_enable.integer)
6640                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6641                 if (r_glsl_postprocess_uservec4_enable.integer)
6642                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6643
6644                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6645                 GL_Color(1, 1, 1, 1);
6646                 GL_BlendFunc(GL_ONE, GL_ZERO);
6647
6648                 switch(vid.renderpath)
6649                 {
6650                 case RENDERPATH_GL20:
6651                 case RENDERPATH_GLES2:
6652                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6653                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6654                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6655                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6656                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6657                         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]);
6658                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6659                         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]);
6660                         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]);
6661                         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]);
6662                         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]);
6663                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6664                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6665                         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);
6666                         break;
6667                 case RENDERPATH_D3D9:
6668 #ifdef SUPPORTD3D
6669                         // 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...
6670                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6671                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6672                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6673                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6674                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6675                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6676                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6677                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6678                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6679                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6680                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6681                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6682                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6683                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6684 #endif
6685                         break;
6686                 case RENDERPATH_D3D10:
6687                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6688                         break;
6689                 case RENDERPATH_D3D11:
6690                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6691                         break;
6692                 case RENDERPATH_SOFT:
6693                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6694                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6695                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6696                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6697                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6698                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6699                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6700                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6701                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6702                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6703                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6704                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6705                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6706                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6707                         break;
6708                 default:
6709                         break;
6710                 }
6711                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6712                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6713                 break;
6714         case RENDERPATH_GL11:
6715         case RENDERPATH_GL13:
6716         case RENDERPATH_GLES1:
6717                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6718                 {
6719                         // apply a color tint to the whole view
6720                         R_ResetViewRendering2D(0, NULL, NULL);
6721                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6722                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6723                         R_SetupShader_Generic_NoTexture(false, true);
6724                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6725                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6726                 }
6727                 break;
6728         }
6729 }
6730
6731 matrix4x4_t r_waterscrollmatrix;
6732
6733 void R_UpdateFog(void)
6734 {
6735         // Nehahra fog
6736         if (gamemode == GAME_NEHAHRA)
6737         {
6738                 if (gl_fogenable.integer)
6739                 {
6740                         r_refdef.oldgl_fogenable = true;
6741                         r_refdef.fog_density = gl_fogdensity.value;
6742                         r_refdef.fog_red = gl_fogred.value;
6743                         r_refdef.fog_green = gl_foggreen.value;
6744                         r_refdef.fog_blue = gl_fogblue.value;
6745                         r_refdef.fog_alpha = 1;
6746                         r_refdef.fog_start = 0;
6747                         r_refdef.fog_end = gl_skyclip.value;
6748                         r_refdef.fog_height = 1<<30;
6749                         r_refdef.fog_fadedepth = 128;
6750                 }
6751                 else if (r_refdef.oldgl_fogenable)
6752                 {
6753                         r_refdef.oldgl_fogenable = false;
6754                         r_refdef.fog_density = 0;
6755                         r_refdef.fog_red = 0;
6756                         r_refdef.fog_green = 0;
6757                         r_refdef.fog_blue = 0;
6758                         r_refdef.fog_alpha = 0;
6759                         r_refdef.fog_start = 0;
6760                         r_refdef.fog_end = 0;
6761                         r_refdef.fog_height = 1<<30;
6762                         r_refdef.fog_fadedepth = 128;
6763                 }
6764         }
6765
6766         // fog parms
6767         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6768         r_refdef.fog_start = max(0, r_refdef.fog_start);
6769         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6770
6771         if (r_refdef.fog_density && r_drawfog.integer)
6772         {
6773                 r_refdef.fogenabled = true;
6774                 // this is the point where the fog reaches 0.9986 alpha, which we
6775                 // consider a good enough cutoff point for the texture
6776                 // (0.9986 * 256 == 255.6)
6777                 if (r_fog_exp2.integer)
6778                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6779                 else
6780                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6781                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6782                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6783                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6784                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6785                         R_BuildFogHeightTexture();
6786                 // fog color was already set
6787                 // update the fog texture
6788                 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)
6789                         R_BuildFogTexture();
6790                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6791                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6792         }
6793         else
6794                 r_refdef.fogenabled = false;
6795
6796         // fog color
6797         if (r_refdef.fog_density)
6798         {
6799                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6800                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6801                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6802
6803                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6804                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6805                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6806                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6807
6808                 {
6809                         vec3_t fogvec;
6810                         VectorCopy(r_refdef.fogcolor, fogvec);
6811                         //   color.rgb *= ContrastBoost * SceneBrightness;
6812                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6813                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6814                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6815                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6816                 }
6817         }
6818 }
6819
6820 void R_UpdateVariables(void)
6821 {
6822         R_Textures_Frame();
6823
6824         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6825
6826         r_refdef.farclip = r_farclip_base.value;
6827         if (r_refdef.scene.worldmodel)
6828                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6829         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6830
6831         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6832                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6833         r_refdef.polygonfactor = 0;
6834         r_refdef.polygonoffset = 0;
6835         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6836         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6837
6838         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6839         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6840         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6841         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6842         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6843         if (FAKELIGHT_ENABLED)
6844         {
6845                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6846         }
6847         else if (r_refdef.scene.worldmodel)
6848         {
6849                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6850         }
6851         if (r_showsurfaces.integer)
6852         {
6853                 r_refdef.scene.rtworld = false;
6854                 r_refdef.scene.rtworldshadows = false;
6855                 r_refdef.scene.rtdlight = false;
6856                 r_refdef.scene.rtdlightshadows = false;
6857                 r_refdef.lightmapintensity = 0;
6858         }
6859
6860         r_gpuskeletal = false;
6861         switch(vid.renderpath)
6862         {
6863         case RENDERPATH_GL20:
6864                 r_gpuskeletal = r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6865         case RENDERPATH_D3D9:
6866         case RENDERPATH_D3D10:
6867         case RENDERPATH_D3D11:
6868         case RENDERPATH_SOFT:
6869         case RENDERPATH_GLES2:
6870                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6871                 {
6872                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6873                         {
6874                                 // build GLSL gamma texture
6875 #define RAMPWIDTH 256
6876                                 unsigned short ramp[RAMPWIDTH * 3];
6877                                 unsigned char rampbgr[RAMPWIDTH][4];
6878                                 int i;
6879
6880                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6881
6882                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6883                                 for(i = 0; i < RAMPWIDTH; ++i)
6884                                 {
6885                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6886                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6887                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6888                                         rampbgr[i][3] = 0;
6889                                 }
6890                                 if (r_texture_gammaramps)
6891                                 {
6892                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6893                                 }
6894                                 else
6895                                 {
6896                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6897                                 }
6898                         }
6899                 }
6900                 else
6901                 {
6902                         // remove GLSL gamma texture
6903                 }
6904                 break;
6905         case RENDERPATH_GL11:
6906         case RENDERPATH_GL13:
6907         case RENDERPATH_GLES1:
6908                 break;
6909         }
6910 }
6911
6912 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6913 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6914 /*
6915 ================
6916 R_SelectScene
6917 ================
6918 */
6919 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6920         if( scenetype != r_currentscenetype ) {
6921                 // store the old scenetype
6922                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6923                 r_currentscenetype = scenetype;
6924                 // move in the new scene
6925                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6926         }
6927 }
6928
6929 /*
6930 ================
6931 R_GetScenePointer
6932 ================
6933 */
6934 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6935 {
6936         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6937         if( scenetype == r_currentscenetype ) {
6938                 return &r_refdef.scene;
6939         } else {
6940                 return &r_scenes_store[ scenetype ];
6941         }
6942 }
6943
6944 static int R_SortEntities_Compare(const void *ap, const void *bp)
6945 {
6946         const entity_render_t *a = *(const entity_render_t **)ap;
6947         const entity_render_t *b = *(const entity_render_t **)bp;
6948
6949         // 1. compare model
6950         if(a->model < b->model)
6951                 return -1;
6952         if(a->model > b->model)
6953                 return +1;
6954
6955         // 2. compare skin
6956         // TODO possibly calculate the REAL skinnum here first using
6957         // skinscenes?
6958         if(a->skinnum < b->skinnum)
6959                 return -1;
6960         if(a->skinnum > b->skinnum)
6961                 return +1;
6962
6963         // everything we compared is equal
6964         return 0;
6965 }
6966 static void R_SortEntities(void)
6967 {
6968         // below or equal 2 ents, sorting never gains anything
6969         if(r_refdef.scene.numentities <= 2)
6970                 return;
6971         // sort
6972         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6973 }
6974
6975 /*
6976 ================
6977 R_RenderView
6978 ================
6979 */
6980 int dpsoftrast_test;
6981 extern cvar_t r_shadow_bouncegrid;
6982 void R_RenderView(void)
6983 {
6984         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6985         int fbo;
6986         rtexture_t *depthtexture;
6987         rtexture_t *colortexture;
6988
6989         dpsoftrast_test = r_test.integer;
6990
6991         if (r_timereport_active)
6992                 R_TimeReport("start");
6993         r_textureframe++; // used only by R_GetCurrentTexture
6994         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6995
6996         if(R_CompileShader_CheckStaticParms())
6997                 R_GLSL_Restart_f();
6998
6999         if (!r_drawentities.integer)
7000                 r_refdef.scene.numentities = 0;
7001         else if (r_sortentities.integer)
7002                 R_SortEntities();
7003
7004         R_AnimCache_ClearCache();
7005         R_FrameData_NewFrame();
7006
7007         /* adjust for stereo display */
7008         if(R_Stereo_Active())
7009         {
7010                 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);
7011                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7012         }
7013
7014         if (r_refdef.view.isoverlay)
7015         {
7016                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7017                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7018                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7019                 R_TimeReport("depthclear");
7020
7021                 r_refdef.view.showdebug = false;
7022
7023                 r_fb.water.enabled = false;
7024                 r_fb.water.numwaterplanes = 0;
7025
7026                 R_RenderScene(0, NULL, NULL);
7027
7028                 r_refdef.view.matrix = originalmatrix;
7029
7030                 CHECKGLERROR
7031                 return;
7032         }
7033
7034         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7035         {
7036                 r_refdef.view.matrix = originalmatrix;
7037                 return;
7038         }
7039
7040         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7041
7042         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7043                 // in sRGB fallback, behave similar to true sRGB: convert this
7044                 // value from linear to sRGB
7045                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7046
7047         R_RenderView_UpdateViewVectors();
7048
7049         R_Shadow_UpdateWorldLightSelection();
7050
7051         R_Bloom_StartFrame();
7052
7053         // apply bloom brightness offset
7054         if(r_fb.bloomtexture[0])
7055                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7056
7057         R_Water_StartFrame();
7058
7059         // now we probably have an fbo to render into
7060         fbo = r_fb.fbo;
7061         depthtexture = r_fb.depthtexture;
7062         colortexture = r_fb.colortexture;
7063
7064         CHECKGLERROR
7065         if (r_timereport_active)
7066                 R_TimeReport("viewsetup");
7067
7068         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7069
7070         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7071         {
7072                 R_ClearScreen(r_refdef.fogenabled);
7073                 if (r_timereport_active)
7074                         R_TimeReport("viewclear");
7075         }
7076         r_refdef.view.clear = true;
7077
7078         r_refdef.view.showdebug = true;
7079
7080         R_View_Update();
7081         if (r_timereport_active)
7082                 R_TimeReport("visibility");
7083
7084         R_AnimCache_CacheVisibleEntities();
7085         if (r_timereport_active)
7086                 R_TimeReport("animcache");
7087
7088         R_Shadow_UpdateBounceGridTexture();
7089         if (r_timereport_active && r_shadow_bouncegrid.integer)
7090                 R_TimeReport("bouncegrid");
7091
7092         r_fb.water.numwaterplanes = 0;
7093         if (r_fb.water.enabled)
7094                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7095
7096         R_RenderScene(fbo, depthtexture, colortexture);
7097         r_fb.water.numwaterplanes = 0;
7098
7099         R_BlendView(fbo, depthtexture, colortexture);
7100         if (r_timereport_active)
7101                 R_TimeReport("blendview");
7102
7103         GL_Scissor(0, 0, vid.width, vid.height);
7104         GL_ScissorTest(false);
7105
7106         r_refdef.view.matrix = originalmatrix;
7107
7108         CHECKGLERROR
7109 }
7110
7111 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7112 {
7113         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7114         {
7115                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7116                 if (r_timereport_active)
7117                         R_TimeReport("waterworld");
7118         }
7119
7120         // don't let sound skip if going slow
7121         if (r_refdef.scene.extraupdate)
7122                 S_ExtraUpdate ();
7123
7124         R_DrawModelsAddWaterPlanes();
7125         if (r_timereport_active)
7126                 R_TimeReport("watermodels");
7127
7128         if (r_fb.water.numwaterplanes)
7129         {
7130                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7131                 if (r_timereport_active)
7132                         R_TimeReport("waterscenes");
7133         }
7134 }
7135
7136 extern cvar_t cl_locs_show;
7137 static void R_DrawLocs(void);
7138 static void R_DrawEntityBBoxes(void);
7139 static void R_DrawModelDecals(void);
7140 extern cvar_t cl_decals_newsystem;
7141 extern qboolean r_shadow_usingdeferredprepass;
7142 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7143 {
7144         qboolean shadowmapping = false;
7145
7146         if (r_timereport_active)
7147                 R_TimeReport("beginscene");
7148
7149         r_refdef.stats[r_stat_renders]++;
7150
7151         R_UpdateFog();
7152
7153         // don't let sound skip if going slow
7154         if (r_refdef.scene.extraupdate)
7155                 S_ExtraUpdate ();
7156
7157         R_MeshQueue_BeginScene();
7158
7159         R_SkyStartFrame();
7160
7161         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);
7162
7163         if (r_timereport_active)
7164                 R_TimeReport("skystartframe");
7165
7166         if (cl.csqc_vidvars.drawworld)
7167         {
7168                 // don't let sound skip if going slow
7169                 if (r_refdef.scene.extraupdate)
7170                         S_ExtraUpdate ();
7171
7172                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7173                 {
7174                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7175                         if (r_timereport_active)
7176                                 R_TimeReport("worldsky");
7177                 }
7178
7179                 if (R_DrawBrushModelsSky() && r_timereport_active)
7180                         R_TimeReport("bmodelsky");
7181
7182                 if (skyrendermasked && skyrenderlater)
7183                 {
7184                         // we have to force off the water clipping plane while rendering sky
7185                         R_SetupView(false, fbo, depthtexture, colortexture);
7186                         R_Sky();
7187                         R_SetupView(true, fbo, depthtexture, colortexture);
7188                         if (r_timereport_active)
7189                                 R_TimeReport("sky");
7190                 }
7191         }
7192
7193         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7194         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7195                 R_Shadow_PrepareModelShadows();
7196         if (r_timereport_active)
7197                 R_TimeReport("preparelights");
7198
7199         if (R_Shadow_ShadowMappingEnabled())
7200                 shadowmapping = true;
7201
7202         if (r_shadow_usingdeferredprepass)
7203                 R_Shadow_DrawPrepass();
7204
7205         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7206         {
7207                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7208                 if (r_timereport_active)
7209                         R_TimeReport("worlddepth");
7210         }
7211         if (r_depthfirst.integer >= 2)
7212         {
7213                 R_DrawModelsDepth();
7214                 if (r_timereport_active)
7215                         R_TimeReport("modeldepth");
7216         }
7217
7218         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7219         {
7220                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7221                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7222                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7223                 // don't let sound skip if going slow
7224                 if (r_refdef.scene.extraupdate)
7225                         S_ExtraUpdate ();
7226         }
7227
7228         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7229         {
7230                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7231                 if (r_timereport_active)
7232                         R_TimeReport("world");
7233         }
7234
7235         // don't let sound skip if going slow
7236         if (r_refdef.scene.extraupdate)
7237                 S_ExtraUpdate ();
7238
7239         R_DrawModels();
7240         if (r_timereport_active)
7241                 R_TimeReport("models");
7242
7243         // don't let sound skip if going slow
7244         if (r_refdef.scene.extraupdate)
7245                 S_ExtraUpdate ();
7246
7247         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7248         {
7249                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7250                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7251                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7252                 // don't let sound skip if going slow
7253                 if (r_refdef.scene.extraupdate)
7254                         S_ExtraUpdate ();
7255         }
7256
7257         if (!r_shadow_usingdeferredprepass)
7258         {
7259                 R_Shadow_DrawLights();
7260                 if (r_timereport_active)
7261                         R_TimeReport("rtlights");
7262         }
7263
7264         // don't let sound skip if going slow
7265         if (r_refdef.scene.extraupdate)
7266                 S_ExtraUpdate ();
7267
7268         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7269         {
7270                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7271                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7272                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7273                 // don't let sound skip if going slow
7274                 if (r_refdef.scene.extraupdate)
7275                         S_ExtraUpdate ();
7276         }
7277
7278         if (cl.csqc_vidvars.drawworld)
7279         {
7280                 if (cl_decals_newsystem.integer)
7281                 {
7282                         R_DrawModelDecals();
7283                         if (r_timereport_active)
7284                                 R_TimeReport("modeldecals");
7285                 }
7286                 else
7287                 {
7288                         R_DrawDecals();
7289                         if (r_timereport_active)
7290                                 R_TimeReport("decals");
7291                 }
7292
7293                 R_DrawParticles();
7294                 if (r_timereport_active)
7295                         R_TimeReport("particles");
7296
7297                 R_DrawExplosions();
7298                 if (r_timereport_active)
7299                         R_TimeReport("explosions");
7300
7301                 R_DrawLightningBeams();
7302                 if (r_timereport_active)
7303                         R_TimeReport("lightning");
7304         }
7305
7306         if (cl.csqc_loaded)
7307                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7308
7309         if (r_refdef.view.showdebug)
7310         {
7311                 if (cl_locs_show.integer)
7312                 {
7313                         R_DrawLocs();
7314                         if (r_timereport_active)
7315                                 R_TimeReport("showlocs");
7316                 }
7317
7318                 if (r_drawportals.integer)
7319                 {
7320                         R_DrawPortals();
7321                         if (r_timereport_active)
7322                                 R_TimeReport("portals");
7323                 }
7324
7325                 if (r_showbboxes.value > 0)
7326                 {
7327                         R_DrawEntityBBoxes();
7328                         if (r_timereport_active)
7329                                 R_TimeReport("bboxes");
7330                 }
7331         }
7332
7333         if (r_transparent.integer)
7334         {
7335                 R_MeshQueue_RenderTransparent();
7336                 if (r_timereport_active)
7337                         R_TimeReport("drawtrans");
7338         }
7339
7340         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))
7341         {
7342                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7343                 if (r_timereport_active)
7344                         R_TimeReport("worlddebug");
7345                 R_DrawModelsDebug();
7346                 if (r_timereport_active)
7347                         R_TimeReport("modeldebug");
7348         }
7349
7350         if (cl.csqc_vidvars.drawworld)
7351         {
7352                 R_Shadow_DrawCoronas();
7353                 if (r_timereport_active)
7354                         R_TimeReport("coronas");
7355         }
7356
7357 #if 0
7358         {
7359                 GL_DepthTest(false);
7360                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7361                 GL_Color(1, 1, 1, 1);
7362                 qglBegin(GL_POLYGON);
7363                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7364                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7365                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7366                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7367                 qglEnd();
7368                 qglBegin(GL_POLYGON);
7369                 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]);
7370                 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]);
7371                 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]);
7372                 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]);
7373                 qglEnd();
7374                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7375         }
7376 #endif
7377
7378         // don't let sound skip if going slow
7379         if (r_refdef.scene.extraupdate)
7380                 S_ExtraUpdate ();
7381 }
7382
7383 static const unsigned short bboxelements[36] =
7384 {
7385         5, 1, 3, 5, 3, 7,
7386         6, 2, 0, 6, 0, 4,
7387         7, 3, 2, 7, 2, 6,
7388         4, 0, 1, 4, 1, 5,
7389         4, 5, 7, 4, 7, 6,
7390         1, 0, 2, 1, 2, 3,
7391 };
7392
7393 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7394 {
7395         int i;
7396         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7397
7398         RSurf_ActiveWorldEntity();
7399
7400         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7401         GL_DepthMask(false);
7402         GL_DepthRange(0, 1);
7403         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7404 //      R_Mesh_ResetTextureState();
7405
7406         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7407         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7408         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7409         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7410         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7411         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7412         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7413         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7414         R_FillColors(color4f, 8, cr, cg, cb, ca);
7415         if (r_refdef.fogenabled)
7416         {
7417                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7418                 {
7419                         f1 = RSurf_FogVertex(v);
7420                         f2 = 1 - f1;
7421                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7422                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7423                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7424                 }
7425         }
7426         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7427         R_Mesh_ResetTextureState();
7428         R_SetupShader_Generic_NoTexture(false, false);
7429         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7430 }
7431
7432 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7433 {
7434         prvm_prog_t *prog = SVVM_prog;
7435         int i;
7436         float color[4];
7437         prvm_edict_t *edict;
7438
7439         // this function draws bounding boxes of server entities
7440         if (!sv.active)
7441                 return;
7442
7443         GL_CullFace(GL_NONE);
7444         R_SetupShader_Generic_NoTexture(false, false);
7445
7446         for (i = 0;i < numsurfaces;i++)
7447         {
7448                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7449                 switch ((int)PRVM_serveredictfloat(edict, solid))
7450                 {
7451                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7452                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7453                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7454                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7455                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7456                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7457                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7458                 }
7459                 color[3] *= r_showbboxes.value;
7460                 color[3] = bound(0, color[3], 1);
7461                 GL_DepthTest(!r_showdisabledepthtest.integer);
7462                 GL_CullFace(r_refdef.view.cullface_front);
7463                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7464         }
7465 }
7466
7467 static void R_DrawEntityBBoxes(void)
7468 {
7469         int i;
7470         prvm_edict_t *edict;
7471         vec3_t center;
7472         prvm_prog_t *prog = SVVM_prog;
7473
7474         // this function draws bounding boxes of server entities
7475         if (!sv.active)
7476                 return;
7477
7478         for (i = 0;i < prog->num_edicts;i++)
7479         {
7480                 edict = PRVM_EDICT_NUM(i);
7481                 if (edict->priv.server->free)
7482                         continue;
7483                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7484                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7485                         continue;
7486                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7487                         continue;
7488                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7489                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7490         }
7491 }
7492
7493 static const int nomodelelement3i[24] =
7494 {
7495         5, 2, 0,
7496         5, 1, 2,
7497         5, 0, 3,
7498         5, 3, 1,
7499         0, 2, 4,
7500         2, 1, 4,
7501         3, 0, 4,
7502         1, 3, 4
7503 };
7504
7505 static const unsigned short nomodelelement3s[24] =
7506 {
7507         5, 2, 0,
7508         5, 1, 2,
7509         5, 0, 3,
7510         5, 3, 1,
7511         0, 2, 4,
7512         2, 1, 4,
7513         3, 0, 4,
7514         1, 3, 4
7515 };
7516
7517 static const float nomodelvertex3f[6*3] =
7518 {
7519         -16,   0,   0,
7520          16,   0,   0,
7521           0, -16,   0,
7522           0,  16,   0,
7523           0,   0, -16,
7524           0,   0,  16
7525 };
7526
7527 static const float nomodelcolor4f[6*4] =
7528 {
7529         0.0f, 0.0f, 0.5f, 1.0f,
7530         0.0f, 0.0f, 0.5f, 1.0f,
7531         0.0f, 0.5f, 0.0f, 1.0f,
7532         0.0f, 0.5f, 0.0f, 1.0f,
7533         0.5f, 0.0f, 0.0f, 1.0f,
7534         0.5f, 0.0f, 0.0f, 1.0f
7535 };
7536
7537 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7538 {
7539         int i;
7540         float f1, f2, *c;
7541         float color4f[6*4];
7542
7543         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);
7544
7545         // this is only called once per entity so numsurfaces is always 1, and
7546         // surfacelist is always {0}, so this code does not handle batches
7547
7548         if (rsurface.ent_flags & RENDER_ADDITIVE)
7549         {
7550                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7551                 GL_DepthMask(false);
7552         }
7553         else if (rsurface.colormod[3] < 1)
7554         {
7555                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7556                 GL_DepthMask(false);
7557         }
7558         else
7559         {
7560                 GL_BlendFunc(GL_ONE, GL_ZERO);
7561                 GL_DepthMask(true);
7562         }
7563         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7564         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7565         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7566         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7567         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7568         for (i = 0, c = color4f;i < 6;i++, c += 4)
7569         {
7570                 c[0] *= rsurface.colormod[0];
7571                 c[1] *= rsurface.colormod[1];
7572                 c[2] *= rsurface.colormod[2];
7573                 c[3] *= rsurface.colormod[3];
7574         }
7575         if (r_refdef.fogenabled)
7576         {
7577                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7578                 {
7579                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7580                         f2 = 1 - f1;
7581                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7582                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7583                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7584                 }
7585         }
7586 //      R_Mesh_ResetTextureState();
7587         R_SetupShader_Generic_NoTexture(false, false);
7588         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7589         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7590 }
7591
7592 void R_DrawNoModel(entity_render_t *ent)
7593 {
7594         vec3_t org;
7595         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7596         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7597                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7598         else
7599                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7600 }
7601
7602 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7603 {
7604         vec3_t right1, right2, diff, normal;
7605
7606         VectorSubtract (org2, org1, normal);
7607
7608         // calculate 'right' vector for start
7609         VectorSubtract (r_refdef.view.origin, org1, diff);
7610         CrossProduct (normal, diff, right1);
7611         VectorNormalize (right1);
7612
7613         // calculate 'right' vector for end
7614         VectorSubtract (r_refdef.view.origin, org2, diff);
7615         CrossProduct (normal, diff, right2);
7616         VectorNormalize (right2);
7617
7618         vert[ 0] = org1[0] + width * right1[0];
7619         vert[ 1] = org1[1] + width * right1[1];
7620         vert[ 2] = org1[2] + width * right1[2];
7621         vert[ 3] = org1[0] - width * right1[0];
7622         vert[ 4] = org1[1] - width * right1[1];
7623         vert[ 5] = org1[2] - width * right1[2];
7624         vert[ 6] = org2[0] - width * right2[0];
7625         vert[ 7] = org2[1] - width * right2[1];
7626         vert[ 8] = org2[2] - width * right2[2];
7627         vert[ 9] = org2[0] + width * right2[0];
7628         vert[10] = org2[1] + width * right2[1];
7629         vert[11] = org2[2] + width * right2[2];
7630 }
7631
7632 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)
7633 {
7634         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7635         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7636         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7637         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7638         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7639         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7640         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7641         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7642         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7643         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7644         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7645         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7646 }
7647
7648 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7649 {
7650         int i;
7651         float *vertex3f;
7652         float v[3];
7653         VectorSet(v, x, y, z);
7654         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7655                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7656                         break;
7657         if (i == mesh->numvertices)
7658         {
7659                 if (mesh->numvertices < mesh->maxvertices)
7660                 {
7661                         VectorCopy(v, vertex3f);
7662                         mesh->numvertices++;
7663                 }
7664                 return mesh->numvertices;
7665         }
7666         else
7667                 return i;
7668 }
7669
7670 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7671 {
7672         int i;
7673         int *e, element[3];
7674         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7675         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7676         e = mesh->element3i + mesh->numtriangles * 3;
7677         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7678         {
7679                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7680                 if (mesh->numtriangles < mesh->maxtriangles)
7681                 {
7682                         *e++ = element[0];
7683                         *e++ = element[1];
7684                         *e++ = element[2];
7685                         mesh->numtriangles++;
7686                 }
7687                 element[1] = element[2];
7688         }
7689 }
7690
7691 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7692 {
7693         int i;
7694         int *e, element[3];
7695         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7696         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7697         e = mesh->element3i + mesh->numtriangles * 3;
7698         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7699         {
7700                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7701                 if (mesh->numtriangles < mesh->maxtriangles)
7702                 {
7703                         *e++ = element[0];
7704                         *e++ = element[1];
7705                         *e++ = element[2];
7706                         mesh->numtriangles++;
7707                 }
7708                 element[1] = element[2];
7709         }
7710 }
7711
7712 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7713 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7714 {
7715         int planenum, planenum2;
7716         int w;
7717         int tempnumpoints;
7718         mplane_t *plane, *plane2;
7719         double maxdist;
7720         double temppoints[2][256*3];
7721         // figure out how large a bounding box we need to properly compute this brush
7722         maxdist = 0;
7723         for (w = 0;w < numplanes;w++)
7724                 maxdist = max(maxdist, fabs(planes[w].dist));
7725         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7726         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7727         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7728         {
7729                 w = 0;
7730                 tempnumpoints = 4;
7731                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7732                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7733                 {
7734                         if (planenum2 == planenum)
7735                                 continue;
7736                         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);
7737                         w = !w;
7738                 }
7739                 if (tempnumpoints < 3)
7740                         continue;
7741                 // generate elements forming a triangle fan for this polygon
7742                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7743         }
7744 }
7745
7746 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)
7747 {
7748         texturelayer_t *layer;
7749         layer = t->currentlayers + t->currentnumlayers++;
7750         layer->type = type;
7751         layer->depthmask = depthmask;
7752         layer->blendfunc1 = blendfunc1;
7753         layer->blendfunc2 = blendfunc2;
7754         layer->texture = texture;
7755         layer->texmatrix = *matrix;
7756         layer->color[0] = r;
7757         layer->color[1] = g;
7758         layer->color[2] = b;
7759         layer->color[3] = a;
7760 }
7761
7762 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7763 {
7764         if(parms[0] == 0 && parms[1] == 0)
7765                 return false;
7766         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7767                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7768                         return false;
7769         return true;
7770 }
7771
7772 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7773 {
7774         double index, f;
7775         index = parms[2] + rsurface.shadertime * parms[3];
7776         index -= floor(index);
7777         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7778         {
7779         default:
7780         case Q3WAVEFUNC_NONE:
7781         case Q3WAVEFUNC_NOISE:
7782         case Q3WAVEFUNC_COUNT:
7783                 f = 0;
7784                 break;
7785         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7786         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7787         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7788         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7789         case Q3WAVEFUNC_TRIANGLE:
7790                 index *= 4;
7791                 f = index - floor(index);
7792                 if (index < 1)
7793                 {
7794                         // f = f;
7795                 }
7796                 else if (index < 2)
7797                         f = 1 - f;
7798                 else if (index < 3)
7799                         f = -f;
7800                 else
7801                         f = -(1 - f);
7802                 break;
7803         }
7804         f = parms[0] + parms[1] * f;
7805         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7806                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7807         return (float) f;
7808 }
7809
7810 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7811 {
7812         int w, h, idx;
7813         double f;
7814         double offsetd[2];
7815         float tcmat[12];
7816         matrix4x4_t matrix, temp;
7817         switch(tcmod->tcmod)
7818         {
7819                 case Q3TCMOD_COUNT:
7820                 case Q3TCMOD_NONE:
7821                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7822                                 matrix = r_waterscrollmatrix;
7823                         else
7824                                 matrix = identitymatrix;
7825                         break;
7826                 case Q3TCMOD_ENTITYTRANSLATE:
7827                         // this is used in Q3 to allow the gamecode to control texcoord
7828                         // scrolling on the entity, which is not supported in darkplaces yet.
7829                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7830                         break;
7831                 case Q3TCMOD_ROTATE:
7832                         f = tcmod->parms[0] * rsurface.shadertime;
7833                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7834                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7835                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7836                         break;
7837                 case Q3TCMOD_SCALE:
7838                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7839                         break;
7840                 case Q3TCMOD_SCROLL:
7841                         // extra care is needed because of precision breakdown with large values of time
7842                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7843                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7844                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7845                         break;
7846                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7847                         w = (int) tcmod->parms[0];
7848                         h = (int) tcmod->parms[1];
7849                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7850                         f = f - floor(f);
7851                         idx = (int) floor(f * w * h);
7852                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7853                         break;
7854                 case Q3TCMOD_STRETCH:
7855                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7856                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7857                         break;
7858                 case Q3TCMOD_TRANSFORM:
7859                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7860                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7861                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7862                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7863                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7864                         break;
7865                 case Q3TCMOD_TURBULENT:
7866                         // this is handled in the RSurf_PrepareVertices function
7867                         matrix = identitymatrix;
7868                         break;
7869         }
7870         temp = *texmatrix;
7871         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7872 }
7873
7874 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7875 {
7876         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7877         char name[MAX_QPATH];
7878         skinframe_t *skinframe;
7879         unsigned char pixels[296*194];
7880         strlcpy(cache->name, skinname, sizeof(cache->name));
7881         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7882         if (developer_loading.integer)
7883                 Con_Printf("loading %s\n", name);
7884         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7885         if (!skinframe || !skinframe->base)
7886         {
7887                 unsigned char *f;
7888                 fs_offset_t filesize;
7889                 skinframe = NULL;
7890                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7891                 if (f)
7892                 {
7893                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7894                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7895                         Mem_Free(f);
7896                 }
7897         }
7898         cache->skinframe = skinframe;
7899 }
7900
7901 texture_t *R_GetCurrentTexture(texture_t *t)
7902 {
7903         int i;
7904         const entity_render_t *ent = rsurface.entity;
7905         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7906         q3shaderinfo_layer_tcmod_t *tcmod;
7907
7908         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7909                 return t->currentframe;
7910         t->update_lastrenderframe = r_textureframe;
7911         t->update_lastrenderentity = (void *)ent;
7912
7913         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7914                 t->camera_entity = ent->entitynumber;
7915         else
7916                 t->camera_entity = 0;
7917
7918         // switch to an alternate material if this is a q1bsp animated material
7919         {
7920                 texture_t *texture = t;
7921                 int s = rsurface.ent_skinnum;
7922                 if ((unsigned int)s >= (unsigned int)model->numskins)
7923                         s = 0;
7924                 if (model->skinscenes)
7925                 {
7926                         if (model->skinscenes[s].framecount > 1)
7927                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7928                         else
7929                                 s = model->skinscenes[s].firstframe;
7930                 }
7931                 if (s > 0)
7932                         t = t + s * model->num_surfaces;
7933                 if (t->animated)
7934                 {
7935                         // use an alternate animation if the entity's frame is not 0,
7936                         // and only if the texture has an alternate animation
7937                         if (rsurface.ent_alttextures && t->anim_total[1])
7938                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7939                         else
7940                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7941                 }
7942                 texture->currentframe = t;
7943         }
7944
7945         // update currentskinframe to be a qw skin or animation frame
7946         if (rsurface.ent_qwskin >= 0)
7947         {
7948                 i = rsurface.ent_qwskin;
7949                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7950                 {
7951                         r_qwskincache_size = cl.maxclients;
7952                         if (r_qwskincache)
7953                                 Mem_Free(r_qwskincache);
7954                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7955                 }
7956                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7957                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7958                 t->currentskinframe = r_qwskincache[i].skinframe;
7959                 if (t->currentskinframe == NULL)
7960                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7961         }
7962         else if (t->numskinframes >= 2)
7963                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7964         if (t->backgroundnumskinframes >= 2)
7965                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7966
7967         t->currentmaterialflags = t->basematerialflags;
7968         t->currentalpha = rsurface.colormod[3];
7969         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7970                 t->currentalpha *= r_wateralpha.value;
7971         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7972                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7973         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7974                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7975         if (!(rsurface.ent_flags & RENDER_LIGHT))
7976                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7977         else if (FAKELIGHT_ENABLED)
7978         {
7979                 // no modellight if using fakelight for the map
7980         }
7981         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7982         {
7983                 // pick a model lighting mode
7984                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7985                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7986                 else
7987                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7988         }
7989         if (rsurface.ent_flags & RENDER_ADDITIVE)
7990                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7991         else if (t->currentalpha < 1)
7992                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7993         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7994         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7995                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7996         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7997                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7998         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7999                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8000         if (t->backgroundnumskinframes)
8001                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8002         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8003         {
8004                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8005                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8006         }
8007         else
8008                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8009         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8010         {
8011                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8012                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8013         }
8014         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8015                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8016
8017         // there is no tcmod
8018         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8019         {
8020                 t->currenttexmatrix = r_waterscrollmatrix;
8021                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8022         }
8023         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8024         {
8025                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8026                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8027         }
8028
8029         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8030                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8031         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8032                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8033
8034         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8035         if (t->currentskinframe->qpixels)
8036                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8037         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8038         if (!t->basetexture)
8039                 t->basetexture = r_texture_notexture;
8040         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8041         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8042         t->nmaptexture = t->currentskinframe->nmap;
8043         if (!t->nmaptexture)
8044                 t->nmaptexture = r_texture_blanknormalmap;
8045         t->glosstexture = r_texture_black;
8046         t->glowtexture = t->currentskinframe->glow;
8047         t->fogtexture = t->currentskinframe->fog;
8048         t->reflectmasktexture = t->currentskinframe->reflect;
8049         if (t->backgroundnumskinframes)
8050         {
8051                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8052                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8053                 t->backgroundglosstexture = r_texture_black;
8054                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8055                 if (!t->backgroundnmaptexture)
8056                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8057                 // make sure that if glow is going to be used, both textures are not NULL
8058                 if (!t->backgroundglowtexture && t->glowtexture)
8059                         t->backgroundglowtexture = r_texture_black;
8060                 if (!t->glowtexture && t->backgroundglowtexture)
8061                         t->glowtexture = r_texture_black;
8062         }
8063         else
8064         {
8065                 t->backgroundbasetexture = r_texture_white;
8066                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8067                 t->backgroundglosstexture = r_texture_black;
8068                 t->backgroundglowtexture = NULL;
8069         }
8070         t->specularpower = r_shadow_glossexponent.value;
8071         // TODO: store reference values for these in the texture?
8072         t->specularscale = 0;
8073         if (r_shadow_gloss.integer > 0)
8074         {
8075                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8076                 {
8077                         if (r_shadow_glossintensity.value > 0)
8078                         {
8079                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8080                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8081                                 t->specularscale = r_shadow_glossintensity.value;
8082                         }
8083                 }
8084                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8085                 {
8086                         t->glosstexture = r_texture_white;
8087                         t->backgroundglosstexture = r_texture_white;
8088                         t->specularscale = r_shadow_gloss2intensity.value;
8089                         t->specularpower = r_shadow_gloss2exponent.value;
8090                 }
8091         }
8092         t->specularscale *= t->specularscalemod;
8093         t->specularpower *= t->specularpowermod;
8094         t->rtlightambient = 0;
8095
8096         // lightmaps mode looks bad with dlights using actual texturing, so turn
8097         // off the colormap and glossmap, but leave the normalmap on as it still
8098         // accurately represents the shading involved
8099         if (gl_lightmaps.integer)
8100         {
8101                 t->basetexture = r_texture_grey128;
8102                 t->pantstexture = r_texture_black;
8103                 t->shirttexture = r_texture_black;
8104                 if (gl_lightmaps.integer < 2)
8105                         t->nmaptexture = r_texture_blanknormalmap;
8106                 t->glosstexture = r_texture_black;
8107                 t->glowtexture = NULL;
8108                 t->fogtexture = NULL;
8109                 t->reflectmasktexture = NULL;
8110                 t->backgroundbasetexture = NULL;
8111                 if (gl_lightmaps.integer < 2)
8112                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8113                 t->backgroundglosstexture = r_texture_black;
8114                 t->backgroundglowtexture = NULL;
8115                 t->specularscale = 0;
8116                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8117         }
8118
8119         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8120         VectorClear(t->dlightcolor);
8121         t->currentnumlayers = 0;
8122         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8123         {
8124                 int blendfunc1, blendfunc2;
8125                 qboolean depthmask;
8126                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8127                 {
8128                         blendfunc1 = GL_SRC_ALPHA;
8129                         blendfunc2 = GL_ONE;
8130                 }
8131                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8132                 {
8133                         blendfunc1 = GL_SRC_ALPHA;
8134                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8135                 }
8136                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8137                 {
8138                         blendfunc1 = t->customblendfunc[0];
8139                         blendfunc2 = t->customblendfunc[1];
8140                 }
8141                 else
8142                 {
8143                         blendfunc1 = GL_ONE;
8144                         blendfunc2 = GL_ZERO;
8145                 }
8146                 // don't colormod evilblend textures
8147                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8148                         VectorSet(t->lightmapcolor, 1, 1, 1);
8149                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8150                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8151                 {
8152                         // fullbright is not affected by r_refdef.lightmapintensity
8153                         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]);
8154                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8155                                 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]);
8156                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8157                                 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]);
8158                 }
8159                 else
8160                 {
8161                         vec3_t ambientcolor;
8162                         float colorscale;
8163                         // set the color tint used for lights affecting this surface
8164                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8165                         colorscale = 2;
8166                         // q3bsp has no lightmap updates, so the lightstylevalue that
8167                         // would normally be baked into the lightmap must be
8168                         // applied to the color
8169                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8170                         if (model->type == mod_brushq3)
8171                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8172                         colorscale *= r_refdef.lightmapintensity;
8173                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8174                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8175                         // basic lit geometry
8176                         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]);
8177                         // add pants/shirt if needed
8178                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8179                                 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]);
8180                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8181                                 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]);
8182                         // now add ambient passes if needed
8183                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8184                         {
8185                                 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]);
8186                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8187                                         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]);
8188                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8189                                         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]);
8190                         }
8191                 }
8192                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8193                         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]);
8194                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8195                 {
8196                         // if this is opaque use alpha blend which will darken the earlier
8197                         // passes cheaply.
8198                         //
8199                         // if this is an alpha blended material, all the earlier passes
8200                         // were darkened by fog already, so we only need to add the fog
8201                         // color ontop through the fog mask texture
8202                         //
8203                         // if this is an additive blended material, all the earlier passes
8204                         // were darkened by fog already, and we should not add fog color
8205                         // (because the background was not darkened, there is no fog color
8206                         // that was lost behind it).
8207                         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]);
8208                 }
8209         }
8210
8211         return t->currentframe;
8212 }
8213
8214 rsurfacestate_t rsurface;
8215
8216 void RSurf_ActiveWorldEntity(void)
8217 {
8218         dp_model_t *model = r_refdef.scene.worldmodel;
8219         //if (rsurface.entity == r_refdef.scene.worldentity)
8220         //      return;
8221         rsurface.entity = r_refdef.scene.worldentity;
8222         rsurface.skeleton = NULL;
8223         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8224         rsurface.ent_skinnum = 0;
8225         rsurface.ent_qwskin = -1;
8226         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8227         rsurface.shadertime = r_refdef.scene.time;
8228         rsurface.matrix = identitymatrix;
8229         rsurface.inversematrix = identitymatrix;
8230         rsurface.matrixscale = 1;
8231         rsurface.inversematrixscale = 1;
8232         R_EntityMatrix(&identitymatrix);
8233         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8234         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8235         rsurface.fograngerecip = r_refdef.fograngerecip;
8236         rsurface.fogheightfade = r_refdef.fogheightfade;
8237         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8238         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8239         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8240         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8241         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8242         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8243         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8244         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8245         rsurface.colormod[3] = 1;
8246         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);
8247         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8248         rsurface.frameblend[0].lerp = 1;
8249         rsurface.ent_alttextures = false;
8250         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8251         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8252         rsurface.entityskeletaltransform3x4 = NULL;
8253         rsurface.entityskeletalnumtransforms = 0;
8254         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8255         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8256         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8257         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8258         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8259         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8260         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8261         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8262         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8263         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8264         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8265         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8266         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8267         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8268         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8269         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8270         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8271         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8272         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8273         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8274         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8275         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8276         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8277         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8278         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8279         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8280         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8281         rsurface.modelelement3i = model->surfmesh.data_element3i;
8282         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8283         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8284         rsurface.modelelement3s = model->surfmesh.data_element3s;
8285         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8286         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8287         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8288         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8289         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8290         rsurface.modelsurfaces = model->data_surfaces;
8291         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8292         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8293         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8294         rsurface.modelgeneratedvertex = false;
8295         rsurface.batchgeneratedvertex = false;
8296         rsurface.batchfirstvertex = 0;
8297         rsurface.batchnumvertices = 0;
8298         rsurface.batchfirsttriangle = 0;
8299         rsurface.batchnumtriangles = 0;
8300         rsurface.batchvertex3f  = NULL;
8301         rsurface.batchvertex3f_vertexbuffer = NULL;
8302         rsurface.batchvertex3f_bufferoffset = 0;
8303         rsurface.batchsvector3f = NULL;
8304         rsurface.batchsvector3f_vertexbuffer = NULL;
8305         rsurface.batchsvector3f_bufferoffset = 0;
8306         rsurface.batchtvector3f = NULL;
8307         rsurface.batchtvector3f_vertexbuffer = NULL;
8308         rsurface.batchtvector3f_bufferoffset = 0;
8309         rsurface.batchnormal3f  = NULL;
8310         rsurface.batchnormal3f_vertexbuffer = NULL;
8311         rsurface.batchnormal3f_bufferoffset = 0;
8312         rsurface.batchlightmapcolor4f = NULL;
8313         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8314         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8315         rsurface.batchtexcoordtexture2f = NULL;
8316         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8317         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8318         rsurface.batchtexcoordlightmap2f = NULL;
8319         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8320         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8321         rsurface.batchskeletalindex4ub = NULL;
8322         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8323         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8324         rsurface.batchskeletalweight4ub = NULL;
8325         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8326         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8327         rsurface.batchvertexmesh = NULL;
8328         rsurface.batchvertexmeshbuffer = NULL;
8329         rsurface.batchvertex3fbuffer = NULL;
8330         rsurface.batchelement3i = NULL;
8331         rsurface.batchelement3i_indexbuffer = NULL;
8332         rsurface.batchelement3i_bufferoffset = 0;
8333         rsurface.batchelement3s = NULL;
8334         rsurface.batchelement3s_indexbuffer = NULL;
8335         rsurface.batchelement3s_bufferoffset = 0;
8336         rsurface.passcolor4f = NULL;
8337         rsurface.passcolor4f_vertexbuffer = NULL;
8338         rsurface.passcolor4f_bufferoffset = 0;
8339         rsurface.forcecurrenttextureupdate = false;
8340 }
8341
8342 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8343 {
8344         dp_model_t *model = ent->model;
8345         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8346         //      return;
8347         rsurface.entity = (entity_render_t *)ent;
8348         rsurface.skeleton = ent->skeleton;
8349         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8350         rsurface.ent_skinnum = ent->skinnum;
8351         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;
8352         rsurface.ent_flags = ent->flags;
8353         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8354         rsurface.matrix = ent->matrix;
8355         rsurface.inversematrix = ent->inversematrix;
8356         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8357         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8358         R_EntityMatrix(&rsurface.matrix);
8359         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8360         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8361         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8362         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8363         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8364         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8365         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8366         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8367         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8368         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8369         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8370         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8371         rsurface.colormod[3] = ent->alpha;
8372         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8373         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8374         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8375         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8376         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8377         if (ent->model->brush.submodel && !prepass)
8378         {
8379                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8380                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8381         }
8382         // if the animcache code decided it should use the shader path, skip the deform step
8383         rsurface.entityskeletaltransform3x4 = ent->animcache_vertex3f ? NULL : ent->animcache_skeletaltransform3x4;
8384         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8385         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8386         {
8387                 if (ent->animcache_vertex3f)
8388                 {
8389                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8390                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8391                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8392                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8393                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8394                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8395                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8396                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8397                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8398                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8399                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8400                 }
8401                 else if (wanttangents)
8402                 {
8403                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8404                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8405                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8406                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8407                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8408                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8409                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8410                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8411                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8412                         rsurface.modelvertexmesh = NULL;
8413                         rsurface.modelvertexmeshbuffer = NULL;
8414                         rsurface.modelvertex3fbuffer = NULL;
8415                 }
8416                 else if (wantnormals)
8417                 {
8418                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8419                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8420                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8421                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8422                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8423                         rsurface.modelsvector3f = NULL;
8424                         rsurface.modeltvector3f = NULL;
8425                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8426                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8427                         rsurface.modelvertexmesh = NULL;
8428                         rsurface.modelvertexmeshbuffer = NULL;
8429                         rsurface.modelvertex3fbuffer = NULL;
8430                 }
8431                 else
8432                 {
8433                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8434                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8435                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8436                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8437                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8438                         rsurface.modelsvector3f = NULL;
8439                         rsurface.modeltvector3f = NULL;
8440                         rsurface.modelnormal3f = NULL;
8441                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8442                         rsurface.modelvertexmesh = NULL;
8443                         rsurface.modelvertexmeshbuffer = NULL;
8444                         rsurface.modelvertex3fbuffer = NULL;
8445                 }
8446                 rsurface.modelvertex3f_vertexbuffer = 0;
8447                 rsurface.modelvertex3f_bufferoffset = 0;
8448                 rsurface.modelsvector3f_vertexbuffer = 0;
8449                 rsurface.modelsvector3f_bufferoffset = 0;
8450                 rsurface.modeltvector3f_vertexbuffer = 0;
8451                 rsurface.modeltvector3f_bufferoffset = 0;
8452                 rsurface.modelnormal3f_vertexbuffer = 0;
8453                 rsurface.modelnormal3f_bufferoffset = 0;
8454                 rsurface.modelgeneratedvertex = true;
8455         }
8456         else
8457         {
8458                 if (rsurface.entityskeletaltransform3x4)
8459                 {
8460                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8461                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8462                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8463                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8464                 }
8465                 else
8466                 {
8467                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8468                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8469                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8470                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8471                 }
8472                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8473                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8474                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8475                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8476                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8477                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8478                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8479                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8480                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8481                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8482                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8483                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8484                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8485                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8486                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8487                 rsurface.modelgeneratedvertex = false;
8488         }
8489         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8490         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8491         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8492         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8493         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8494         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8495         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8496         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8497         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8498         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8499         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8500         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8501         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8502         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8503         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8504         rsurface.modelelement3i = model->surfmesh.data_element3i;
8505         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8506         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8507         rsurface.modelelement3s = model->surfmesh.data_element3s;
8508         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8509         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8510         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8511         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8512         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8513         rsurface.modelsurfaces = model->data_surfaces;
8514         rsurface.batchgeneratedvertex = false;
8515         rsurface.batchfirstvertex = 0;
8516         rsurface.batchnumvertices = 0;
8517         rsurface.batchfirsttriangle = 0;
8518         rsurface.batchnumtriangles = 0;
8519         rsurface.batchvertex3f  = NULL;
8520         rsurface.batchvertex3f_vertexbuffer = NULL;
8521         rsurface.batchvertex3f_bufferoffset = 0;
8522         rsurface.batchsvector3f = NULL;
8523         rsurface.batchsvector3f_vertexbuffer = NULL;
8524         rsurface.batchsvector3f_bufferoffset = 0;
8525         rsurface.batchtvector3f = NULL;
8526         rsurface.batchtvector3f_vertexbuffer = NULL;
8527         rsurface.batchtvector3f_bufferoffset = 0;
8528         rsurface.batchnormal3f  = NULL;
8529         rsurface.batchnormal3f_vertexbuffer = NULL;
8530         rsurface.batchnormal3f_bufferoffset = 0;
8531         rsurface.batchlightmapcolor4f = NULL;
8532         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8533         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8534         rsurface.batchtexcoordtexture2f = NULL;
8535         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8536         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8537         rsurface.batchtexcoordlightmap2f = NULL;
8538         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8539         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8540         rsurface.batchskeletalindex4ub = NULL;
8541         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8542         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8543         rsurface.batchskeletalweight4ub = NULL;
8544         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8545         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8546         rsurface.batchvertexmesh = NULL;
8547         rsurface.batchvertexmeshbuffer = NULL;
8548         rsurface.batchvertex3fbuffer = NULL;
8549         rsurface.batchelement3i = NULL;
8550         rsurface.batchelement3i_indexbuffer = NULL;
8551         rsurface.batchelement3i_bufferoffset = 0;
8552         rsurface.batchelement3s = NULL;
8553         rsurface.batchelement3s_indexbuffer = NULL;
8554         rsurface.batchelement3s_bufferoffset = 0;
8555         rsurface.passcolor4f = NULL;
8556         rsurface.passcolor4f_vertexbuffer = NULL;
8557         rsurface.passcolor4f_bufferoffset = 0;
8558         rsurface.forcecurrenttextureupdate = false;
8559 }
8560
8561 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)
8562 {
8563         rsurface.entity = r_refdef.scene.worldentity;
8564         rsurface.skeleton = NULL;
8565         rsurface.ent_skinnum = 0;
8566         rsurface.ent_qwskin = -1;
8567         rsurface.ent_flags = entflags;
8568         rsurface.shadertime = r_refdef.scene.time - shadertime;
8569         rsurface.modelnumvertices = numvertices;
8570         rsurface.modelnumtriangles = numtriangles;
8571         rsurface.matrix = *matrix;
8572         rsurface.inversematrix = *inversematrix;
8573         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8574         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8575         R_EntityMatrix(&rsurface.matrix);
8576         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8577         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8578         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8579         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8580         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8581         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8582         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8583         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8584         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8585         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8586         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8587         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8588         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);
8589         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8590         rsurface.frameblend[0].lerp = 1;
8591         rsurface.ent_alttextures = false;
8592         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8593         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8594         rsurface.entityskeletaltransform3x4 = NULL;
8595         rsurface.entityskeletalnumtransforms = 0;
8596         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8597         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8598         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8599         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8600         if (wanttangents)
8601         {
8602                 rsurface.modelvertex3f = (float *)vertex3f;
8603                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8604                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8605                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8606         }
8607         else if (wantnormals)
8608         {
8609                 rsurface.modelvertex3f = (float *)vertex3f;
8610                 rsurface.modelsvector3f = NULL;
8611                 rsurface.modeltvector3f = NULL;
8612                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8613         }
8614         else
8615         {
8616                 rsurface.modelvertex3f = (float *)vertex3f;
8617                 rsurface.modelsvector3f = NULL;
8618                 rsurface.modeltvector3f = NULL;
8619                 rsurface.modelnormal3f = NULL;
8620         }
8621         rsurface.modelvertexmesh = NULL;
8622         rsurface.modelvertexmeshbuffer = NULL;
8623         rsurface.modelvertex3fbuffer = NULL;
8624         rsurface.modelvertex3f_vertexbuffer = 0;
8625         rsurface.modelvertex3f_bufferoffset = 0;
8626         rsurface.modelsvector3f_vertexbuffer = 0;
8627         rsurface.modelsvector3f_bufferoffset = 0;
8628         rsurface.modeltvector3f_vertexbuffer = 0;
8629         rsurface.modeltvector3f_bufferoffset = 0;
8630         rsurface.modelnormal3f_vertexbuffer = 0;
8631         rsurface.modelnormal3f_bufferoffset = 0;
8632         rsurface.modelgeneratedvertex = true;
8633         rsurface.modellightmapcolor4f  = (float *)color4f;
8634         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8635         rsurface.modellightmapcolor4f_bufferoffset = 0;
8636         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8637         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8638         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8639         rsurface.modeltexcoordlightmap2f  = NULL;
8640         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8641         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8642         rsurface.modelskeletalindex4ub = NULL;
8643         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8644         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8645         rsurface.modelskeletalweight4ub = NULL;
8646         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8647         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8648         rsurface.modelelement3i = (int *)element3i;
8649         rsurface.modelelement3i_indexbuffer = NULL;
8650         rsurface.modelelement3i_bufferoffset = 0;
8651         rsurface.modelelement3s = (unsigned short *)element3s;
8652         rsurface.modelelement3s_indexbuffer = NULL;
8653         rsurface.modelelement3s_bufferoffset = 0;
8654         rsurface.modellightmapoffsets = NULL;
8655         rsurface.modelsurfaces = NULL;
8656         rsurface.batchgeneratedvertex = false;
8657         rsurface.batchfirstvertex = 0;
8658         rsurface.batchnumvertices = 0;
8659         rsurface.batchfirsttriangle = 0;
8660         rsurface.batchnumtriangles = 0;
8661         rsurface.batchvertex3f  = NULL;
8662         rsurface.batchvertex3f_vertexbuffer = NULL;
8663         rsurface.batchvertex3f_bufferoffset = 0;
8664         rsurface.batchsvector3f = NULL;
8665         rsurface.batchsvector3f_vertexbuffer = NULL;
8666         rsurface.batchsvector3f_bufferoffset = 0;
8667         rsurface.batchtvector3f = NULL;
8668         rsurface.batchtvector3f_vertexbuffer = NULL;
8669         rsurface.batchtvector3f_bufferoffset = 0;
8670         rsurface.batchnormal3f  = NULL;
8671         rsurface.batchnormal3f_vertexbuffer = NULL;
8672         rsurface.batchnormal3f_bufferoffset = 0;
8673         rsurface.batchlightmapcolor4f = NULL;
8674         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8675         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8676         rsurface.batchtexcoordtexture2f = NULL;
8677         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8678         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8679         rsurface.batchtexcoordlightmap2f = NULL;
8680         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8681         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8682         rsurface.batchskeletalindex4ub = NULL;
8683         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8684         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8685         rsurface.batchskeletalweight4ub = NULL;
8686         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8687         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8688         rsurface.batchvertexmesh = NULL;
8689         rsurface.batchvertexmeshbuffer = NULL;
8690         rsurface.batchvertex3fbuffer = NULL;
8691         rsurface.batchelement3i = NULL;
8692         rsurface.batchelement3i_indexbuffer = NULL;
8693         rsurface.batchelement3i_bufferoffset = 0;
8694         rsurface.batchelement3s = NULL;
8695         rsurface.batchelement3s_indexbuffer = NULL;
8696         rsurface.batchelement3s_bufferoffset = 0;
8697         rsurface.passcolor4f = NULL;
8698         rsurface.passcolor4f_vertexbuffer = NULL;
8699         rsurface.passcolor4f_bufferoffset = 0;
8700         rsurface.forcecurrenttextureupdate = true;
8701
8702         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8703         {
8704                 if ((wantnormals || wanttangents) && !normal3f)
8705                 {
8706                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8707                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8708                 }
8709                 if (wanttangents && !svector3f)
8710                 {
8711                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8712                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8713                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8714                 }
8715         }
8716 }
8717
8718 float RSurf_FogPoint(const float *v)
8719 {
8720         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8721         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8722         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8723         float FogHeightFade = r_refdef.fogheightfade;
8724         float fogfrac;
8725         unsigned int fogmasktableindex;
8726         if (r_refdef.fogplaneviewabove)
8727                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8728         else
8729                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8730         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8731         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8732 }
8733
8734 float RSurf_FogVertex(const float *v)
8735 {
8736         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8737         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8738         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8739         float FogHeightFade = rsurface.fogheightfade;
8740         float fogfrac;
8741         unsigned int fogmasktableindex;
8742         if (r_refdef.fogplaneviewabove)
8743                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8744         else
8745                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8746         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8747         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8748 }
8749
8750 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8751 {
8752         int i;
8753         for (i = 0;i < numelements;i++)
8754                 outelement3i[i] = inelement3i[i] + adjust;
8755 }
8756
8757 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8758 extern cvar_t gl_vbo;
8759 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8760 {
8761         int deformindex;
8762         int firsttriangle;
8763         int numtriangles;
8764         int firstvertex;
8765         int endvertex;
8766         int numvertices;
8767         int surfacefirsttriangle;
8768         int surfacenumtriangles;
8769         int surfacefirstvertex;
8770         int surfaceendvertex;
8771         int surfacenumvertices;
8772         int batchnumsurfaces = texturenumsurfaces;
8773         int batchnumvertices;
8774         int batchnumtriangles;
8775         int needsupdate;
8776         int i, j;
8777         qboolean gaps;
8778         qboolean dynamicvertex;
8779         float amplitude;
8780         float animpos;
8781         float scale;
8782         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8783         float waveparms[4];
8784         unsigned char *ub;
8785         q3shaderinfo_deform_t *deform;
8786         const msurface_t *surface, *firstsurface;
8787         r_vertexmesh_t *vertexmesh;
8788         if (!texturenumsurfaces)
8789                 return;
8790         // find vertex range of this surface batch
8791         gaps = false;
8792         firstsurface = texturesurfacelist[0];
8793         firsttriangle = firstsurface->num_firsttriangle;
8794         batchnumvertices = 0;
8795         batchnumtriangles = 0;
8796         firstvertex = endvertex = firstsurface->num_firstvertex;
8797         for (i = 0;i < texturenumsurfaces;i++)
8798         {
8799                 surface = texturesurfacelist[i];
8800                 if (surface != firstsurface + i)
8801                         gaps = true;
8802                 surfacefirstvertex = surface->num_firstvertex;
8803                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8804                 surfacenumvertices = surface->num_vertices;
8805                 surfacenumtriangles = surface->num_triangles;
8806                 if (firstvertex > surfacefirstvertex)
8807                         firstvertex = surfacefirstvertex;
8808                 if (endvertex < surfaceendvertex)
8809                         endvertex = surfaceendvertex;
8810                 batchnumvertices += surfacenumvertices;
8811                 batchnumtriangles += surfacenumtriangles;
8812         }
8813
8814         r_refdef.stats[r_stat_batch_batches]++;
8815         if (gaps)
8816                 r_refdef.stats[r_stat_batch_withgaps]++;
8817         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8818         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8819         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8820
8821         // we now know the vertex range used, and if there are any gaps in it
8822         rsurface.batchfirstvertex = firstvertex;
8823         rsurface.batchnumvertices = endvertex - firstvertex;
8824         rsurface.batchfirsttriangle = firsttriangle;
8825         rsurface.batchnumtriangles = batchnumtriangles;
8826
8827         // this variable holds flags for which properties have been updated that
8828         // may require regenerating vertexmesh array...
8829         needsupdate = 0;
8830
8831         // check if any dynamic vertex processing must occur
8832         dynamicvertex = false;
8833
8834         // a cvar to force the dynamic vertex path to be taken, for debugging
8835         if (r_batch_debugdynamicvertexpath.integer)
8836         {
8837                 if (!dynamicvertex)
8838                 {
8839                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8840                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8841                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8842                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8843                 }
8844                 dynamicvertex = true;
8845         }
8846
8847         // if there is a chance of animated vertex colors, it's a dynamic batch
8848         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8849         {
8850                 if (!dynamicvertex)
8851                 {
8852                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
8853                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
8854                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
8855                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
8856                 }
8857                 dynamicvertex = true;
8858                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8859         }
8860
8861         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8862         {
8863                 switch (deform->deform)
8864                 {
8865                 default:
8866                 case Q3DEFORM_PROJECTIONSHADOW:
8867                 case Q3DEFORM_TEXT0:
8868                 case Q3DEFORM_TEXT1:
8869                 case Q3DEFORM_TEXT2:
8870                 case Q3DEFORM_TEXT3:
8871                 case Q3DEFORM_TEXT4:
8872                 case Q3DEFORM_TEXT5:
8873                 case Q3DEFORM_TEXT6:
8874                 case Q3DEFORM_TEXT7:
8875                 case Q3DEFORM_NONE:
8876                         break;
8877                 case Q3DEFORM_AUTOSPRITE:
8878                         if (!dynamicvertex)
8879                         {
8880                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
8881                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
8882                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
8883                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
8884                         }
8885                         dynamicvertex = true;
8886                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8887                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8888                         break;
8889                 case Q3DEFORM_AUTOSPRITE2:
8890                         if (!dynamicvertex)
8891                         {
8892                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
8893                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
8894                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
8895                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
8896                         }
8897                         dynamicvertex = true;
8898                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8899                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8900                         break;
8901                 case Q3DEFORM_NORMAL:
8902                         if (!dynamicvertex)
8903                         {
8904                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
8905                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
8906                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
8907                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
8908                         }
8909                         dynamicvertex = true;
8910                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8911                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8912                         break;
8913                 case Q3DEFORM_WAVE:
8914                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8915                                 break; // if wavefunc is a nop, ignore this transform
8916                         if (!dynamicvertex)
8917                         {
8918                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
8919                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
8920                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
8921                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
8922                         }
8923                         dynamicvertex = true;
8924                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8925                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8926                         break;
8927                 case Q3DEFORM_BULGE:
8928                         if (!dynamicvertex)
8929                         {
8930                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
8931                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
8932                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
8933                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
8934                         }
8935                         dynamicvertex = true;
8936                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8937                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8938                         break;
8939                 case Q3DEFORM_MOVE:
8940                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8941                                 break; // if wavefunc is a nop, ignore this transform
8942                         if (!dynamicvertex)
8943                         {
8944                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
8945                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
8946                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
8947                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
8948                         }
8949                         dynamicvertex = true;
8950                         batchneed |= BATCHNEED_ARRAY_VERTEX;
8951                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8952                         break;
8953                 }
8954         }
8955         switch(rsurface.texture->tcgen.tcgen)
8956         {
8957         default:
8958         case Q3TCGEN_TEXTURE:
8959                 break;
8960         case Q3TCGEN_LIGHTMAP:
8961                 if (!dynamicvertex)
8962                 {
8963                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
8964                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
8965                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
8966                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
8967                 }
8968                 dynamicvertex = true;
8969                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8970                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8971                 break;
8972         case Q3TCGEN_VECTOR:
8973                 if (!dynamicvertex)
8974                 {
8975                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
8976                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
8977                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
8978                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
8979                 }
8980                 dynamicvertex = true;
8981                 batchneed |= BATCHNEED_ARRAY_VERTEX;
8982                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8983                 break;
8984         case Q3TCGEN_ENVIRONMENT:
8985                 if (!dynamicvertex)
8986                 {
8987                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
8988                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
8989                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
8990                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
8991                 }
8992                 dynamicvertex = true;
8993                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
8994                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8995                 break;
8996         }
8997         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8998         {
8999                 if (!dynamicvertex)
9000                 {
9001                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9002                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9003                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9004                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9005                 }
9006                 dynamicvertex = true;
9007                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9008                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9009         }
9010
9011         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9012         {
9013                 if (!dynamicvertex)
9014                 {
9015                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9016                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9017                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9018                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9019                 }
9020                 dynamicvertex = true;
9021                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9022         }
9023
9024         // when the model data has no vertex buffer (dynamic mesh), we need to
9025         // eliminate gaps
9026         if (vid.useinterleavedarrays && !rsurface.modelvertexmeshbuffer)
9027                 batchneed |= BATCHNEED_NOGAPS;
9028
9029         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9030         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9031         // we ensure this by treating the vertex batch as dynamic...
9032         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9033         {
9034                 if (!dynamicvertex)
9035                 {
9036                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9037                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9038                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9039                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9040                 }
9041                 dynamicvertex = true;
9042         }
9043
9044         if (dynamicvertex)
9045         {
9046                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9047                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9048                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9049                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9050                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9051                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9052                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9053                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9054         }
9055
9056         // if needsupdate, we have to do a dynamic vertex batch for sure
9057         if (needsupdate & batchneed)
9058         {
9059                 if (!dynamicvertex)
9060                 {
9061                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9062                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9063                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9064                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9065                 }
9066                 dynamicvertex = true;
9067         }
9068
9069         // see if we need to build vertexmesh from arrays
9070         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9071         {
9072                 if (!dynamicvertex)
9073                 {
9074                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9075                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9076                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9077                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9078                 }
9079                 dynamicvertex = true;
9080         }
9081
9082         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9083         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9084                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9085
9086         rsurface.batchvertex3f = rsurface.modelvertex3f;
9087         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9088         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9089         rsurface.batchsvector3f = rsurface.modelsvector3f;
9090         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9091         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9092         rsurface.batchtvector3f = rsurface.modeltvector3f;
9093         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9094         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9095         rsurface.batchnormal3f = rsurface.modelnormal3f;
9096         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9097         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9098         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9099         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9100         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9101         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9102         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9103         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9104         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9105         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9106         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9107         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9108         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9109         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9110         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9111         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9112         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9113         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
9114         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9115         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
9116         rsurface.batchelement3i = rsurface.modelelement3i;
9117         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9118         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9119         rsurface.batchelement3s = rsurface.modelelement3s;
9120         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9121         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9122         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9123         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9124
9125         // if any dynamic vertex processing has to occur in software, we copy the
9126         // entire surface list together before processing to rebase the vertices
9127         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9128         //
9129         // if any gaps exist and we do not have a static vertex buffer, we have to
9130         // copy the surface list together to avoid wasting upload bandwidth on the
9131         // vertices in the gaps.
9132         //
9133         // if gaps exist and we have a static vertex buffer, we can choose whether
9134         // to combine the index buffer ranges into one dynamic index buffer or
9135         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9136         //
9137         // in many cases the batch is reduced to one draw call.
9138
9139         rsurface.batchmultidraw = false;
9140         rsurface.batchmultidrawnumsurfaces = 0;
9141         rsurface.batchmultidrawsurfacelist = NULL;
9142
9143         if (!dynamicvertex)
9144         {
9145                 // static vertex data, just set pointers...
9146                 rsurface.batchgeneratedvertex = false;
9147                 // if there are gaps, we want to build a combined index buffer,
9148                 // otherwise use the original static buffer with an appropriate offset
9149                 if (gaps)
9150                 {
9151                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9152                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9153                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9154                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9155                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9156                         {
9157                                 rsurface.batchmultidraw = true;
9158                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9159                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9160                                 return;
9161                         }
9162                         // build a new triangle elements array for this batch
9163                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9164                         rsurface.batchfirsttriangle = 0;
9165                         numtriangles = 0;
9166                         for (i = 0;i < texturenumsurfaces;i++)
9167                         {
9168                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9169                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9170                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9171                                 numtriangles += surfacenumtriangles;
9172                         }
9173                         rsurface.batchelement3i_indexbuffer = NULL;
9174                         rsurface.batchelement3i_bufferoffset = 0;
9175                         rsurface.batchelement3s = NULL;
9176                         rsurface.batchelement3s_indexbuffer = NULL;
9177                         rsurface.batchelement3s_bufferoffset = 0;
9178                         if (endvertex <= 65536)
9179                         {
9180                                 // make a 16bit (unsigned short) index array if possible
9181                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9182                                 for (i = 0;i < numtriangles*3;i++)
9183                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9184                         }
9185                 }
9186                 else
9187                 {
9188                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9189                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9190                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9191                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9192                 }
9193                 return;
9194         }
9195
9196         // something needs software processing, do it for real...
9197         // we only directly handle separate array data in this case and then
9198         // generate interleaved data if needed...
9199         rsurface.batchgeneratedvertex = true;
9200         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9201         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9202         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9203         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9204
9205         // now copy the vertex data into a combined array and make an index array
9206         // (this is what Quake3 does all the time)
9207         // we also apply any skeletal animation here that would have been done in
9208         // the vertex shader, because most of the dynamic vertex animation cases
9209         // need actual vertex positions and normals
9210         //if (dynamicvertex)
9211         {
9212                 rsurface.batchvertex3fbuffer = NULL;
9213                 rsurface.batchvertexmesh = NULL;
9214                 rsurface.batchvertexmeshbuffer = NULL;
9215                 rsurface.batchvertex3f = NULL;
9216                 rsurface.batchvertex3f_vertexbuffer = NULL;
9217                 rsurface.batchvertex3f_bufferoffset = 0;
9218                 rsurface.batchsvector3f = NULL;
9219                 rsurface.batchsvector3f_vertexbuffer = NULL;
9220                 rsurface.batchsvector3f_bufferoffset = 0;
9221                 rsurface.batchtvector3f = NULL;
9222                 rsurface.batchtvector3f_vertexbuffer = NULL;
9223                 rsurface.batchtvector3f_bufferoffset = 0;
9224                 rsurface.batchnormal3f = NULL;
9225                 rsurface.batchnormal3f_vertexbuffer = NULL;
9226                 rsurface.batchnormal3f_bufferoffset = 0;
9227                 rsurface.batchlightmapcolor4f = NULL;
9228                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9229                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9230                 rsurface.batchtexcoordtexture2f = NULL;
9231                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9232                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9233                 rsurface.batchtexcoordlightmap2f = NULL;
9234                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9235                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9236                 rsurface.batchskeletalindex4ub = NULL;
9237                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9238                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9239                 rsurface.batchskeletalweight4ub = NULL;
9240                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9241                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9242                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9243                 rsurface.batchelement3i_indexbuffer = NULL;
9244                 rsurface.batchelement3i_bufferoffset = 0;
9245                 rsurface.batchelement3s = NULL;
9246                 rsurface.batchelement3s_indexbuffer = NULL;
9247                 rsurface.batchelement3s_bufferoffset = 0;
9248                 // we'll only be setting up certain arrays as needed
9249                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9250                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9251                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9252                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9253                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9254                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9255                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9256                 {
9257                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9258                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9259                 }
9260                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9261                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9262                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9263                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9264                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9265                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9266                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9267                 {
9268                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9269                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9270                 }
9271                 numvertices = 0;
9272                 numtriangles = 0;
9273                 for (i = 0;i < texturenumsurfaces;i++)
9274                 {
9275                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9276                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9277                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9278                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9279                         // copy only the data requested
9280                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9281                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9282                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9283                         {
9284                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9285                                 {
9286                                         if (rsurface.batchvertex3f)
9287                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9288                                         else
9289                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9290                                 }
9291                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9292                                 {
9293                                         if (rsurface.modelnormal3f)
9294                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9295                                         else
9296                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9297                                 }
9298                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9299                                 {
9300                                         if (rsurface.modelsvector3f)
9301                                         {
9302                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9303                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9304                                         }
9305                                         else
9306                                         {
9307                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9308                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9309                                         }
9310                                 }
9311                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9312                                 {
9313                                         if (rsurface.modellightmapcolor4f)
9314                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9315                                         else
9316                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9317                                 }
9318                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9319                                 {
9320                                         if (rsurface.modeltexcoordtexture2f)
9321                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9322                                         else
9323                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9324                                 }
9325                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9326                                 {
9327                                         if (rsurface.modeltexcoordlightmap2f)
9328                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9329                                         else
9330                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9331                                 }
9332                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9333                                 {
9334                                         if (rsurface.modelskeletalindex4ub)
9335                                         {
9336                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9337                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9338                                         }
9339                                         else
9340                                         {
9341                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9342                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9343                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9344                                                 for (j = 0;j < surfacenumvertices;j++)
9345                                                         ub[j*4] = 255;
9346                                         }
9347                                 }
9348                         }
9349                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9350                         numvertices += surfacenumvertices;
9351                         numtriangles += surfacenumtriangles;
9352                 }
9353
9354                 // generate a 16bit index array as well if possible
9355                 // (in general, dynamic batches fit)
9356                 if (numvertices <= 65536)
9357                 {
9358                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9359                         for (i = 0;i < numtriangles*3;i++)
9360                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9361                 }
9362
9363                 // since we've copied everything, the batch now starts at 0
9364                 rsurface.batchfirstvertex = 0;
9365                 rsurface.batchnumvertices = batchnumvertices;
9366                 rsurface.batchfirsttriangle = 0;
9367                 rsurface.batchnumtriangles = batchnumtriangles;
9368         }
9369
9370         // apply skeletal animation that would have been done in the vertex shader
9371         if (rsurface.batchskeletaltransform3x4)
9372         {
9373                 const unsigned char *si;
9374                 const unsigned char *sw;
9375                 const float *t[4];
9376                 const float *b = rsurface.batchskeletaltransform3x4;
9377                 float *vp, *vs, *vt, *vn;
9378                 float w[4];
9379                 float m[3][4], n[3][4];
9380                 float tp[3], ts[3], tt[3], tn[3];
9381                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9382                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9383                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9384                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9385                 si = rsurface.batchskeletalindex4ub;
9386                 sw = rsurface.batchskeletalweight4ub;
9387                 vp = rsurface.batchvertex3f;
9388                 vs = rsurface.batchsvector3f;
9389                 vt = rsurface.batchtvector3f;
9390                 vn = rsurface.batchnormal3f;
9391                 memset(m[0], 0, sizeof(m));
9392                 memset(n[0], 0, sizeof(n));
9393                 for (i = 0;i < batchnumvertices;i++)
9394                 {
9395                         t[0] = b + si[0]*12;
9396                         if (sw[0] == 255)
9397                         {
9398                                 // common case - only one matrix
9399                                 m[0][0] = t[0][ 0];
9400                                 m[0][1] = t[0][ 1];
9401                                 m[0][2] = t[0][ 2];
9402                                 m[0][3] = t[0][ 3];
9403                                 m[1][0] = t[0][ 4];
9404                                 m[1][1] = t[0][ 5];
9405                                 m[1][2] = t[0][ 6];
9406                                 m[1][3] = t[0][ 7];
9407                                 m[2][0] = t[0][ 8];
9408                                 m[2][1] = t[0][ 9];
9409                                 m[2][2] = t[0][10];
9410                                 m[2][3] = t[0][11];
9411                         }
9412                         else if (sw[2] + sw[3])
9413                         {
9414                                 // blend 4 matrices
9415                                 t[1] = b + si[1]*12;
9416                                 t[2] = b + si[2]*12;
9417                                 t[3] = b + si[3]*12;
9418                                 w[0] = sw[0] * (1.0f / 255.0f);
9419                                 w[1] = sw[1] * (1.0f / 255.0f);
9420                                 w[2] = sw[2] * (1.0f / 255.0f);
9421                                 w[3] = sw[3] * (1.0f / 255.0f);
9422                                 // blend the matrices
9423                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9424                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9425                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9426                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9427                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9428                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9429                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9430                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9431                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9432                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9433                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9434                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9435                         }
9436                         else
9437                         {
9438                                 // blend 2 matrices
9439                                 t[1] = b + si[1]*12;
9440                                 w[0] = sw[0] * (1.0f / 255.0f);
9441                                 w[1] = sw[1] * (1.0f / 255.0f);
9442                                 // blend the matrices
9443                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9444                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9445                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9446                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9447                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9448                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9449                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9450                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9451                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9452                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9453                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9454                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9455                         }
9456                         si += 4;
9457                         sw += 4;
9458                         // modify the vertex
9459                         VectorCopy(vp, tp);
9460                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9461                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9462                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9463                         vp += 3;
9464                         if (vn)
9465                         {
9466                                 // the normal transformation matrix is a set of cross products...
9467                                 CrossProduct(m[1], m[2], n[0]);
9468                                 CrossProduct(m[2], m[0], n[1]);
9469                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9470                                 VectorCopy(vn, tn);
9471                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9472                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9473                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9474                                 VectorNormalize(vn);
9475                                 vn += 3;
9476                                 if (vs)
9477                                 {
9478                                         VectorCopy(vs, ts);
9479                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9480                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9481                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9482                                         VectorNormalize(vs);
9483                                         vs += 3;
9484                                         VectorCopy(vt, tt);
9485                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9486                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9487                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9488                                         VectorNormalize(vt);
9489                                         vt += 3;
9490                                 }
9491                         }
9492                 }
9493                 rsurface.batchskeletaltransform3x4 = NULL;
9494                 rsurface.batchskeletalnumtransforms = 0;
9495         }
9496
9497         // q1bsp surfaces rendered in vertex color mode have to have colors
9498         // calculated based on lightstyles
9499         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9500         {
9501                 // generate color arrays for the surfaces in this list
9502                 int c[4];
9503                 int scale;
9504                 int size3;
9505                 const int *offsets;
9506                 const unsigned char *lm;
9507                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9508                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9509                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9510                 numvertices = 0;
9511                 for (i = 0;i < texturenumsurfaces;i++)
9512                 {
9513                         surface = texturesurfacelist[i];
9514                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9515                         surfacenumvertices = surface->num_vertices;
9516                         if (surface->lightmapinfo->samples)
9517                         {
9518                                 for (j = 0;j < surfacenumvertices;j++)
9519                                 {
9520                                         lm = surface->lightmapinfo->samples + offsets[j];
9521                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9522                                         VectorScale(lm, scale, c);
9523                                         if (surface->lightmapinfo->styles[1] != 255)
9524                                         {
9525                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9526                                                 lm += size3;
9527                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9528                                                 VectorMA(c, scale, lm, c);
9529                                                 if (surface->lightmapinfo->styles[2] != 255)
9530                                                 {
9531                                                         lm += size3;
9532                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9533                                                         VectorMA(c, scale, lm, c);
9534                                                         if (surface->lightmapinfo->styles[3] != 255)
9535                                                         {
9536                                                                 lm += size3;
9537                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9538                                                                 VectorMA(c, scale, lm, c);
9539                                                         }
9540                                                 }
9541                                         }
9542                                         c[0] >>= 7;
9543                                         c[1] >>= 7;
9544                                         c[2] >>= 7;
9545                                         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);
9546                                         numvertices++;
9547                                 }
9548                         }
9549                         else
9550                         {
9551                                 for (j = 0;j < surfacenumvertices;j++)
9552                                 {
9553                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9554                                         numvertices++;
9555                                 }
9556                         }
9557                 }
9558         }
9559
9560         // if vertices are deformed (sprite flares and things in maps, possibly
9561         // water waves, bulges and other deformations), modify the copied vertices
9562         // in place
9563         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9564         {
9565                 switch (deform->deform)
9566                 {
9567                 default:
9568                 case Q3DEFORM_PROJECTIONSHADOW:
9569                 case Q3DEFORM_TEXT0:
9570                 case Q3DEFORM_TEXT1:
9571                 case Q3DEFORM_TEXT2:
9572                 case Q3DEFORM_TEXT3:
9573                 case Q3DEFORM_TEXT4:
9574                 case Q3DEFORM_TEXT5:
9575                 case Q3DEFORM_TEXT6:
9576                 case Q3DEFORM_TEXT7:
9577                 case Q3DEFORM_NONE:
9578                         break;
9579                 case Q3DEFORM_AUTOSPRITE:
9580                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9581                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9582                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9583                         VectorNormalize(newforward);
9584                         VectorNormalize(newright);
9585                         VectorNormalize(newup);
9586 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9587 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9588 //                      rsurface.batchvertex3f_bufferoffset = 0;
9589 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9590 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9591 //                      rsurface.batchsvector3f_bufferoffset = 0;
9592 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9593 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9594 //                      rsurface.batchtvector3f_bufferoffset = 0;
9595 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9596 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9597 //                      rsurface.batchnormal3f_bufferoffset = 0;
9598                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9599                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9600                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9601                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9602                                 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);
9603                         // a single autosprite surface can contain multiple sprites...
9604                         for (j = 0;j < batchnumvertices - 3;j += 4)
9605                         {
9606                                 VectorClear(center);
9607                                 for (i = 0;i < 4;i++)
9608                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9609                                 VectorScale(center, 0.25f, center);
9610                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9611                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9612                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9613                                 for (i = 0;i < 4;i++)
9614                                 {
9615                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9616                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9617                                 }
9618                         }
9619                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9620                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9621                         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);
9622                         break;
9623                 case Q3DEFORM_AUTOSPRITE2:
9624                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9625                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9626                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9627                         VectorNormalize(newforward);
9628                         VectorNormalize(newright);
9629                         VectorNormalize(newup);
9630 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9631 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9632 //                      rsurface.batchvertex3f_bufferoffset = 0;
9633                         {
9634                                 const float *v1, *v2;
9635                                 vec3_t start, end;
9636                                 float f, l;
9637                                 struct
9638                                 {
9639                                         float length2;
9640                                         const float *v1;
9641                                         const float *v2;
9642                                 }
9643                                 shortest[2];
9644                                 memset(shortest, 0, sizeof(shortest));
9645                                 // a single autosprite surface can contain multiple sprites...
9646                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9647                                 {
9648                                         VectorClear(center);
9649                                         for (i = 0;i < 4;i++)
9650                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9651                                         VectorScale(center, 0.25f, center);
9652                                         // find the two shortest edges, then use them to define the
9653                                         // axis vectors for rotating around the central axis
9654                                         for (i = 0;i < 6;i++)
9655                                         {
9656                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9657                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9658                                                 l = VectorDistance2(v1, v2);
9659                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9660                                                 if (v1[2] != v2[2])
9661                                                         l += (1.0f / 1024.0f);
9662                                                 if (shortest[0].length2 > l || i == 0)
9663                                                 {
9664                                                         shortest[1] = shortest[0];
9665                                                         shortest[0].length2 = l;
9666                                                         shortest[0].v1 = v1;
9667                                                         shortest[0].v2 = v2;
9668                                                 }
9669                                                 else if (shortest[1].length2 > l || i == 1)
9670                                                 {
9671                                                         shortest[1].length2 = l;
9672                                                         shortest[1].v1 = v1;
9673                                                         shortest[1].v2 = v2;
9674                                                 }
9675                                         }
9676                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9677                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9678                                         // this calculates the right vector from the shortest edge
9679                                         // and the up vector from the edge midpoints
9680                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9681                                         VectorNormalize(right);
9682                                         VectorSubtract(end, start, up);
9683                                         VectorNormalize(up);
9684                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9685                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9686                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9687                                         VectorNegate(forward, forward);
9688                                         VectorReflect(forward, 0, up, forward);
9689                                         VectorNormalize(forward);
9690                                         CrossProduct(up, forward, newright);
9691                                         VectorNormalize(newright);
9692                                         // rotate the quad around the up axis vector, this is made
9693                                         // especially easy by the fact we know the quad is flat,
9694                                         // so we only have to subtract the center position and
9695                                         // measure distance along the right vector, and then
9696                                         // multiply that by the newright vector and add back the
9697                                         // center position
9698                                         // we also need to subtract the old position to undo the
9699                                         // displacement from the center, which we do with a
9700                                         // DotProduct, the subtraction/addition of center is also
9701                                         // optimized into DotProducts here
9702                                         l = DotProduct(right, center);
9703                                         for (i = 0;i < 4;i++)
9704                                         {
9705                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9706                                                 f = DotProduct(right, v1) - l;
9707                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9708                                         }
9709                                 }
9710                         }
9711                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9712                         {
9713 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9714 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9715 //                              rsurface.batchnormal3f_bufferoffset = 0;
9716                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9717                         }
9718                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9719                         {
9720 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9721 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9722 //                              rsurface.batchsvector3f_bufferoffset = 0;
9723 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9724 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9725 //                              rsurface.batchtvector3f_bufferoffset = 0;
9726                                 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);
9727                         }
9728                         break;
9729                 case Q3DEFORM_NORMAL:
9730                         // deform the normals to make reflections wavey
9731                         rsurface.batchnormal3f = (float *)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                                 float vertex[3];
9737                                 float *normal = rsurface.batchnormal3f + 3*j;
9738                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9739                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9740                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9741                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9742                                 VectorNormalize(normal);
9743                         }
9744                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9745                         {
9746 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9747 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9748 //                              rsurface.batchsvector3f_bufferoffset = 0;
9749 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9750 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9751 //                              rsurface.batchtvector3f_bufferoffset = 0;
9752                                 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);
9753                         }
9754                         break;
9755                 case Q3DEFORM_WAVE:
9756                         // deform vertex array to make wavey water and flags and such
9757                         waveparms[0] = deform->waveparms[0];
9758                         waveparms[1] = deform->waveparms[1];
9759                         waveparms[2] = deform->waveparms[2];
9760                         waveparms[3] = deform->waveparms[3];
9761                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9762                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9763                         // this is how a divisor of vertex influence on deformation
9764                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9765                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9766 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9767 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9768 //                      rsurface.batchvertex3f_bufferoffset = 0;
9769 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9770 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9771 //                      rsurface.batchnormal3f_bufferoffset = 0;
9772                         for (j = 0;j < batchnumvertices;j++)
9773                         {
9774                                 // if the wavefunc depends on time, evaluate it per-vertex
9775                                 if (waveparms[3])
9776                                 {
9777                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9778                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9779                                 }
9780                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9781                         }
9782                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9783                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9784                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9785                         {
9786 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9787 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9788 //                              rsurface.batchsvector3f_bufferoffset = 0;
9789 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9790 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9791 //                              rsurface.batchtvector3f_bufferoffset = 0;
9792                                 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);
9793                         }
9794                         break;
9795                 case Q3DEFORM_BULGE:
9796                         // deform vertex array to make the surface have moving bulges
9797 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9798 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9799 //                      rsurface.batchvertex3f_bufferoffset = 0;
9800 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9801 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9802 //                      rsurface.batchnormal3f_bufferoffset = 0;
9803                         for (j = 0;j < batchnumvertices;j++)
9804                         {
9805                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9806                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9807                         }
9808                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9809                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9810                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9811                         {
9812 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9813 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9814 //                              rsurface.batchsvector3f_bufferoffset = 0;
9815 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9816 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9817 //                              rsurface.batchtvector3f_bufferoffset = 0;
9818                                 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);
9819                         }
9820                         break;
9821                 case Q3DEFORM_MOVE:
9822                         // deform vertex array
9823                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9824                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9825                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9826                         VectorScale(deform->parms, scale, waveparms);
9827 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9828 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9829 //                      rsurface.batchvertex3f_bufferoffset = 0;
9830                         for (j = 0;j < batchnumvertices;j++)
9831                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9832                         break;
9833                 }
9834         }
9835
9836         // generate texcoords based on the chosen texcoord source
9837         switch(rsurface.texture->tcgen.tcgen)
9838         {
9839         default:
9840         case Q3TCGEN_TEXTURE:
9841                 break;
9842         case Q3TCGEN_LIGHTMAP:
9843 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9844 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9845 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9846                 if (rsurface.batchtexcoordlightmap2f)
9847                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9848                 break;
9849         case Q3TCGEN_VECTOR:
9850 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9851 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9852 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9853                 for (j = 0;j < batchnumvertices;j++)
9854                 {
9855                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9856                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9857                 }
9858                 break;
9859         case Q3TCGEN_ENVIRONMENT:
9860                 // make environment reflections using a spheremap
9861                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9862                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9863                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9864                 for (j = 0;j < batchnumvertices;j++)
9865                 {
9866                         // identical to Q3A's method, but executed in worldspace so
9867                         // carried models can be shiny too
9868
9869                         float viewer[3], d, reflected[3], worldreflected[3];
9870
9871                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9872                         // VectorNormalize(viewer);
9873
9874                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9875
9876                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9877                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9878                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9879                         // note: this is proportinal to viewer, so we can normalize later
9880
9881                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9882                         VectorNormalize(worldreflected);
9883
9884                         // note: this sphere map only uses world x and z!
9885                         // so positive and negative y will LOOK THE SAME.
9886                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9887                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9888                 }
9889                 break;
9890         }
9891         // the only tcmod that needs software vertex processing is turbulent, so
9892         // check for it here and apply the changes if needed
9893         // and we only support that as the first one
9894         // (handling a mixture of turbulent and other tcmods would be problematic
9895         //  without punting it entirely to a software path)
9896         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9897         {
9898                 amplitude = rsurface.texture->tcmods[0].parms[1];
9899                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9900 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9901 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9902 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9903                 for (j = 0;j < batchnumvertices;j++)
9904                 {
9905                         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);
9906                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9907                 }
9908         }
9909
9910         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9911         {
9912                 // convert the modified arrays to vertex structs
9913 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9914 //              rsurface.batchvertexmeshbuffer = NULL;
9915                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9916                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9917                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9918                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9919                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9920                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9921                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9922                 {
9923                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9924                         {
9925                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9926                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9927                         }
9928                 }
9929                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9930                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9931                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9932                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9933                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9934                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9935                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9936                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9937                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9938                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9939                 {
9940                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9941                         {
9942                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9943                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9944                         }
9945                 }
9946         }
9947 }
9948
9949 void RSurf_DrawBatch(void)
9950 {
9951         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9952         // through the pipeline, killing it earlier in the pipeline would have
9953         // per-surface overhead rather than per-batch overhead, so it's best to
9954         // reject it here, before it hits glDraw.
9955         if (rsurface.batchnumtriangles == 0)
9956                 return;
9957 #if 0
9958         // batch debugging code
9959         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9960         {
9961                 int i;
9962                 int j;
9963                 int c;
9964                 const int *e;
9965                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9966                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9967                 {
9968                         c = e[i];
9969                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9970                         {
9971                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9972                                 {
9973                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9974                                                 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);
9975                                         break;
9976                                 }
9977                         }
9978                 }
9979         }
9980 #endif
9981         if (rsurface.batchmultidraw)
9982         {
9983                 // issue multiple draws rather than copying index data
9984                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
9985                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
9986                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
9987                 for (i = 0;i < numsurfaces;)
9988                 {
9989                         // combine consecutive surfaces as one draw
9990                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
9991                                 if (surfacelist[j] != surfacelist[k] + 1)
9992                                         break;
9993                         firstvertex = surfacelist[i]->num_firstvertex;
9994                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
9995                         firsttriangle = surfacelist[i]->num_firsttriangle;
9996                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
9997                         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);
9998                         i = j;
9999                 }
10000         }
10001         else
10002         {
10003                 // there is only one consecutive run of index data (may have been combined)
10004                 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);
10005         }
10006 }
10007
10008 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10009 {
10010         // pick the closest matching water plane
10011         int planeindex, vertexindex, bestplaneindex = -1;
10012         float d, bestd;
10013         vec3_t vert;
10014         const float *v;
10015         r_waterstate_waterplane_t *p;
10016         qboolean prepared = false;
10017         bestd = 0;
10018         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10019         {
10020                 if(p->camera_entity != rsurface.texture->camera_entity)
10021                         continue;
10022                 d = 0;
10023                 if(!prepared)
10024                 {
10025                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10026                         prepared = true;
10027                         if(rsurface.batchnumvertices == 0)
10028                                 break;
10029                 }
10030                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10031                 {
10032                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10033                         d += fabs(PlaneDiff(vert, &p->plane));
10034                 }
10035                 if (bestd > d || bestplaneindex < 0)
10036                 {
10037                         bestd = d;
10038                         bestplaneindex = planeindex;
10039                 }
10040         }
10041         return bestplaneindex;
10042         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10043         // this situation though, as it might be better to render single larger
10044         // batches with useless stuff (backface culled for example) than to
10045         // render multiple smaller batches
10046 }
10047
10048 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10049 {
10050         int i;
10051         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10052         rsurface.passcolor4f_vertexbuffer = 0;
10053         rsurface.passcolor4f_bufferoffset = 0;
10054         for (i = 0;i < rsurface.batchnumvertices;i++)
10055                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10056 }
10057
10058 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10059 {
10060         int i;
10061         float f;
10062         const float *v;
10063         const float *c;
10064         float *c2;
10065         if (rsurface.passcolor4f)
10066         {
10067                 // generate color arrays
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;
10076                         c2[1] = c[1] * f;
10077                         c2[2] = c[2] * f;
10078                         c2[3] = c[3];
10079                 }
10080         }
10081         else
10082         {
10083                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10084                 rsurface.passcolor4f_vertexbuffer = 0;
10085                 rsurface.passcolor4f_bufferoffset = 0;
10086                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10087                 {
10088                         f = RSurf_FogVertex(v);
10089                         c2[0] = f;
10090                         c2[1] = f;
10091                         c2[2] = f;
10092                         c2[3] = 1;
10093                 }
10094         }
10095 }
10096
10097 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10098 {
10099         int i;
10100         float f;
10101         const float *v;
10102         const float *c;
10103         float *c2;
10104         if (!rsurface.passcolor4f)
10105                 return;
10106         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10107         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10108         rsurface.passcolor4f_vertexbuffer = 0;
10109         rsurface.passcolor4f_bufferoffset = 0;
10110         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)
10111         {
10112                 f = RSurf_FogVertex(v);
10113                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10114                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10115                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10116                 c2[3] = c[3];
10117         }
10118 }
10119
10120 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10121 {
10122         int i;
10123         const float *c;
10124         float *c2;
10125         if (!rsurface.passcolor4f)
10126                 return;
10127         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10128         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10129         rsurface.passcolor4f_vertexbuffer = 0;
10130         rsurface.passcolor4f_bufferoffset = 0;
10131         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10132         {
10133                 c2[0] = c[0] * r;
10134                 c2[1] = c[1] * g;
10135                 c2[2] = c[2] * b;
10136                 c2[3] = c[3] * a;
10137         }
10138 }
10139
10140 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10141 {
10142         int i;
10143         const float *c;
10144         float *c2;
10145         if (!rsurface.passcolor4f)
10146                 return;
10147         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10148         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10149         rsurface.passcolor4f_vertexbuffer = 0;
10150         rsurface.passcolor4f_bufferoffset = 0;
10151         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10152         {
10153                 c2[0] = c[0] + r_refdef.scene.ambient;
10154                 c2[1] = c[1] + r_refdef.scene.ambient;
10155                 c2[2] = c[2] + r_refdef.scene.ambient;
10156                 c2[3] = c[3];
10157         }
10158 }
10159
10160 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10161 {
10162         // TODO: optimize
10163         rsurface.passcolor4f = NULL;
10164         rsurface.passcolor4f_vertexbuffer = 0;
10165         rsurface.passcolor4f_bufferoffset = 0;
10166         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10167         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10168         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10169         GL_Color(r, g, b, a);
10170         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10171         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10172         R_Mesh_TexMatrix(0, NULL);
10173         RSurf_DrawBatch();
10174 }
10175
10176 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10177 {
10178         // TODO: optimize applyfog && applycolor case
10179         // just apply fog if necessary, and tint the fog color array if necessary
10180         rsurface.passcolor4f = NULL;
10181         rsurface.passcolor4f_vertexbuffer = 0;
10182         rsurface.passcolor4f_bufferoffset = 0;
10183         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10184         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10185         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10186         GL_Color(r, g, b, a);
10187         RSurf_DrawBatch();
10188 }
10189
10190 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10191 {
10192         // TODO: optimize
10193         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10194         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10195         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10196         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10197         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10198         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10199         GL_Color(r, g, b, a);
10200         RSurf_DrawBatch();
10201 }
10202
10203 static void RSurf_DrawBatch_GL11_ClampColor(void)
10204 {
10205         int i;
10206         const float *c1;
10207         float *c2;
10208         if (!rsurface.passcolor4f)
10209                 return;
10210         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10211         {
10212                 c2[0] = bound(0.0f, c1[0], 1.0f);
10213                 c2[1] = bound(0.0f, c1[1], 1.0f);
10214                 c2[2] = bound(0.0f, c1[2], 1.0f);
10215                 c2[3] = bound(0.0f, c1[3], 1.0f);
10216         }
10217 }
10218
10219 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10220 {
10221         int i;
10222         float f;
10223         const float *v;
10224         const float *n;
10225         float *c;
10226         //vec3_t eyedir;
10227
10228         // fake shading
10229         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10230         rsurface.passcolor4f_vertexbuffer = 0;
10231         rsurface.passcolor4f_bufferoffset = 0;
10232         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)
10233         {
10234                 f = -DotProduct(r_refdef.view.forward, n);
10235                 f = max(0, f);
10236                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10237                 f *= r_refdef.lightmapintensity;
10238                 Vector4Set(c, f, f, f, 1);
10239         }
10240 }
10241
10242 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10243 {
10244         RSurf_DrawBatch_GL11_ApplyFakeLight();
10245         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10246         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10247         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10248         GL_Color(r, g, b, a);
10249         RSurf_DrawBatch();
10250 }
10251
10252 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10253 {
10254         int i;
10255         float f;
10256         float alpha;
10257         const float *v;
10258         const float *n;
10259         float *c;
10260         vec3_t ambientcolor;
10261         vec3_t diffusecolor;
10262         vec3_t lightdir;
10263         // TODO: optimize
10264         // model lighting
10265         VectorCopy(rsurface.modellight_lightdir, lightdir);
10266         f = 0.5f * r_refdef.lightmapintensity;
10267         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10268         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10269         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10270         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10271         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10272         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10273         alpha = *a;
10274         if (VectorLength2(diffusecolor) > 0)
10275         {
10276                 // q3-style directional shading
10277                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10278                 rsurface.passcolor4f_vertexbuffer = 0;
10279                 rsurface.passcolor4f_bufferoffset = 0;
10280                 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)
10281                 {
10282                         if ((f = DotProduct(n, lightdir)) > 0)
10283                                 VectorMA(ambientcolor, f, diffusecolor, c);
10284                         else
10285                                 VectorCopy(ambientcolor, c);
10286                         c[3] = alpha;
10287                 }
10288                 *r = 1;
10289                 *g = 1;
10290                 *b = 1;
10291                 *a = 1;
10292                 *applycolor = false;
10293         }
10294         else
10295         {
10296                 *r = ambientcolor[0];
10297                 *g = ambientcolor[1];
10298                 *b = ambientcolor[2];
10299                 rsurface.passcolor4f = NULL;
10300                 rsurface.passcolor4f_vertexbuffer = 0;
10301                 rsurface.passcolor4f_bufferoffset = 0;
10302         }
10303 }
10304
10305 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10306 {
10307         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10308         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10309         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10310         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10311         GL_Color(r, g, b, a);
10312         RSurf_DrawBatch();
10313 }
10314
10315 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10316 {
10317         int i;
10318         float f;
10319         const float *v;
10320         float *c;
10321
10322         // fake shading
10323         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10324         rsurface.passcolor4f_vertexbuffer = 0;
10325         rsurface.passcolor4f_bufferoffset = 0;
10326
10327         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10328         {
10329                 f = 1 - RSurf_FogVertex(v);
10330                 c[0] = r;
10331                 c[1] = g;
10332                 c[2] = b;
10333                 c[3] = f * a;
10334         }
10335 }
10336
10337 void RSurf_SetupDepthAndCulling(void)
10338 {
10339         // submodels are biased to avoid z-fighting with world surfaces that they
10340         // may be exactly overlapping (avoids z-fighting artifacts on certain
10341         // doors and things in Quake maps)
10342         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10343         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10344         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10345         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10346 }
10347
10348 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10349 {
10350         // transparent sky would be ridiculous
10351         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10352                 return;
10353         R_SetupShader_Generic_NoTexture(false, false);
10354         skyrenderlater = true;
10355         RSurf_SetupDepthAndCulling();
10356         GL_DepthMask(true);
10357         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10358         // skymasking on them, and Quake3 never did sky masking (unlike
10359         // software Quake and software Quake2), so disable the sky masking
10360         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10361         // and skymasking also looks very bad when noclipping outside the
10362         // level, so don't use it then either.
10363         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10364         {
10365                 R_Mesh_ResetTextureState();
10366                 if (skyrendermasked)
10367                 {
10368                         R_SetupShader_DepthOrShadow(false, false, false);
10369                         // depth-only (masking)
10370                         GL_ColorMask(0,0,0,0);
10371                         // just to make sure that braindead drivers don't draw
10372                         // anything despite that colormask...
10373                         GL_BlendFunc(GL_ZERO, GL_ONE);
10374                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10375                         if (rsurface.batchvertex3fbuffer)
10376                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10377                         else
10378                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10379                 }
10380                 else
10381                 {
10382                         R_SetupShader_Generic_NoTexture(false, false);
10383                         // fog sky
10384                         GL_BlendFunc(GL_ONE, GL_ZERO);
10385                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10386                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10387                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10388                 }
10389                 RSurf_DrawBatch();
10390                 if (skyrendermasked)
10391                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10392         }
10393         R_Mesh_ResetTextureState();
10394         GL_Color(1, 1, 1, 1);
10395 }
10396
10397 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10398 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10399 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10400 {
10401         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10402                 return;
10403         if (prepass)
10404         {
10405                 // render screenspace normalmap to texture
10406                 GL_DepthMask(true);
10407                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10408                 RSurf_DrawBatch();
10409                 return;
10410         }
10411
10412         // bind lightmap texture
10413
10414         // water/refraction/reflection/camera surfaces have to be handled specially
10415         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10416         {
10417                 int start, end, startplaneindex;
10418                 for (start = 0;start < texturenumsurfaces;start = end)
10419                 {
10420                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10421                         if(startplaneindex < 0)
10422                         {
10423                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10424                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10425                                 end = start + 1;
10426                                 continue;
10427                         }
10428                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10429                                 ;
10430                         // now that we have a batch using the same planeindex, render it
10431                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10432                         {
10433                                 // render water or distortion background
10434                                 GL_DepthMask(true);
10435                                 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);
10436                                 RSurf_DrawBatch();
10437                                 // blend surface on top
10438                                 GL_DepthMask(false);
10439                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10440                                 RSurf_DrawBatch();
10441                         }
10442                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10443                         {
10444                                 // render surface with reflection texture as input
10445                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10446                                 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);
10447                                 RSurf_DrawBatch();
10448                         }
10449                 }
10450                 return;
10451         }
10452
10453         // render surface batch normally
10454         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10455         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);
10456         RSurf_DrawBatch();
10457 }
10458
10459 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10460 {
10461         // OpenGL 1.3 path - anything not completely ancient
10462         qboolean applycolor;
10463         qboolean applyfog;
10464         int layerindex;
10465         const texturelayer_t *layer;
10466         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);
10467         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10468
10469         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10470         {
10471                 vec4_t layercolor;
10472                 int layertexrgbscale;
10473                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10474                 {
10475                         if (layerindex == 0)
10476                                 GL_AlphaTest(true);
10477                         else
10478                         {
10479                                 GL_AlphaTest(false);
10480                                 GL_DepthFunc(GL_EQUAL);
10481                         }
10482                 }
10483                 GL_DepthMask(layer->depthmask && writedepth);
10484                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10485                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10486                 {
10487                         layertexrgbscale = 4;
10488                         VectorScale(layer->color, 0.25f, layercolor);
10489                 }
10490                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10491                 {
10492                         layertexrgbscale = 2;
10493                         VectorScale(layer->color, 0.5f, layercolor);
10494                 }
10495                 else
10496                 {
10497                         layertexrgbscale = 1;
10498                         VectorScale(layer->color, 1.0f, layercolor);
10499                 }
10500                 layercolor[3] = layer->color[3];
10501                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10502                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10503                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10504                 switch (layer->type)
10505                 {
10506                 case TEXTURELAYERTYPE_LITTEXTURE:
10507                         // single-pass lightmapped texture with 2x rgbscale
10508                         R_Mesh_TexBind(0, r_texture_white);
10509                         R_Mesh_TexMatrix(0, NULL);
10510                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10511                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10512                         R_Mesh_TexBind(1, layer->texture);
10513                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10514                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10515                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10516                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10517                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10518                         else if (FAKELIGHT_ENABLED)
10519                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10520                         else if (rsurface.uselightmaptexture)
10521                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10522                         else
10523                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10524                         break;
10525                 case TEXTURELAYERTYPE_TEXTURE:
10526                         // singletexture unlit texture with transparency support
10527                         R_Mesh_TexBind(0, layer->texture);
10528                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10529                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10530                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10531                         R_Mesh_TexBind(1, 0);
10532                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10533                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10534                         break;
10535                 case TEXTURELAYERTYPE_FOG:
10536                         // singletexture fogging
10537                         if (layer->texture)
10538                         {
10539                                 R_Mesh_TexBind(0, layer->texture);
10540                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10541                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10542                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10543                         }
10544                         else
10545                         {
10546                                 R_Mesh_TexBind(0, 0);
10547                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10548                         }
10549                         R_Mesh_TexBind(1, 0);
10550                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10551                         // generate a color array for the fog pass
10552                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10553                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10554                         RSurf_DrawBatch();
10555                         break;
10556                 default:
10557                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10558                 }
10559         }
10560         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10561         {
10562                 GL_DepthFunc(GL_LEQUAL);
10563                 GL_AlphaTest(false);
10564         }
10565 }
10566
10567 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10568 {
10569         // OpenGL 1.1 - crusty old voodoo path
10570         qboolean applyfog;
10571         int layerindex;
10572         const texturelayer_t *layer;
10573         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);
10574         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10575
10576         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10577         {
10578                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10579                 {
10580                         if (layerindex == 0)
10581                                 GL_AlphaTest(true);
10582                         else
10583                         {
10584                                 GL_AlphaTest(false);
10585                                 GL_DepthFunc(GL_EQUAL);
10586                         }
10587                 }
10588                 GL_DepthMask(layer->depthmask && writedepth);
10589                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10590                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10591                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10592                 switch (layer->type)
10593                 {
10594                 case TEXTURELAYERTYPE_LITTEXTURE:
10595                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10596                         {
10597                                 // two-pass lit texture with 2x rgbscale
10598                                 // first the lightmap pass
10599                                 R_Mesh_TexBind(0, r_texture_white);
10600                                 R_Mesh_TexMatrix(0, NULL);
10601                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10602                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10603                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10604                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10605                                 else if (FAKELIGHT_ENABLED)
10606                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10607                                 else if (rsurface.uselightmaptexture)
10608                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10609                                 else
10610                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10611                                 // then apply the texture to it
10612                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10613                                 R_Mesh_TexBind(0, layer->texture);
10614                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10615                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10616                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10617                                 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);
10618                         }
10619                         else
10620                         {
10621                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10622                                 R_Mesh_TexBind(0, layer->texture);
10623                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10624                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10625                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10626                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10627                                         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);
10628                                 else if (FAKELIGHT_ENABLED)
10629                                         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);
10630                                 else
10631                                         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);
10632                         }
10633                         break;
10634                 case TEXTURELAYERTYPE_TEXTURE:
10635                         // singletexture unlit texture with transparency support
10636                         R_Mesh_TexBind(0, layer->texture);
10637                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10638                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10639                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10640                         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);
10641                         break;
10642                 case TEXTURELAYERTYPE_FOG:
10643                         // singletexture fogging
10644                         if (layer->texture)
10645                         {
10646                                 R_Mesh_TexBind(0, layer->texture);
10647                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10648                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10649                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10650                         }
10651                         else
10652                         {
10653                                 R_Mesh_TexBind(0, 0);
10654                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10655                         }
10656                         // generate a color array for the fog pass
10657                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10658                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10659                         RSurf_DrawBatch();
10660                         break;
10661                 default:
10662                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10663                 }
10664         }
10665         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10666         {
10667                 GL_DepthFunc(GL_LEQUAL);
10668                 GL_AlphaTest(false);
10669         }
10670 }
10671
10672 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10673 {
10674         int vi;
10675         int j;
10676         r_vertexgeneric_t *batchvertex;
10677         float c[4];
10678
10679 //      R_Mesh_ResetTextureState();
10680         R_SetupShader_Generic_NoTexture(false, false);
10681
10682         if(rsurface.texture && rsurface.texture->currentskinframe)
10683         {
10684                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10685                 c[3] *= rsurface.texture->currentalpha;
10686         }
10687         else
10688         {
10689                 c[0] = 1;
10690                 c[1] = 0;
10691                 c[2] = 1;
10692                 c[3] = 1;
10693         }
10694
10695         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10696         {
10697                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10698                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10699                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10700         }
10701
10702         // brighten it up (as texture value 127 means "unlit")
10703         c[0] *= 2 * r_refdef.view.colorscale;
10704         c[1] *= 2 * r_refdef.view.colorscale;
10705         c[2] *= 2 * r_refdef.view.colorscale;
10706
10707         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10708                 c[3] *= r_wateralpha.value;
10709
10710         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10711         {
10712                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10713                 GL_DepthMask(false);
10714         }
10715         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10716         {
10717                 GL_BlendFunc(GL_ONE, GL_ONE);
10718                 GL_DepthMask(false);
10719         }
10720         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10721         {
10722                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10723                 GL_DepthMask(false);
10724         }
10725         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10726         {
10727                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10728                 GL_DepthMask(false);
10729         }
10730         else
10731         {
10732                 GL_BlendFunc(GL_ONE, GL_ZERO);
10733                 GL_DepthMask(writedepth);
10734         }
10735
10736         if (r_showsurfaces.integer == 3)
10737         {
10738                 rsurface.passcolor4f = NULL;
10739
10740                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10741                 {
10742                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10743
10744                         rsurface.passcolor4f = NULL;
10745                         rsurface.passcolor4f_vertexbuffer = 0;
10746                         rsurface.passcolor4f_bufferoffset = 0;
10747                 }
10748                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10749                 {
10750                         qboolean applycolor = true;
10751                         float one = 1.0;
10752
10753                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10754
10755                         r_refdef.lightmapintensity = 1;
10756                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10757                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10758                 }
10759                 else if (FAKELIGHT_ENABLED)
10760                 {
10761                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10762
10763                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10764                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10765                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10766                 }
10767                 else
10768                 {
10769                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10770
10771                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10772                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10773                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10774                 }
10775
10776                 if(!rsurface.passcolor4f)
10777                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10778
10779                 RSurf_DrawBatch_GL11_ApplyAmbient();
10780                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10781                 if(r_refdef.fogenabled)
10782                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10783                 RSurf_DrawBatch_GL11_ClampColor();
10784
10785                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10786                 R_SetupShader_Generic_NoTexture(false, false);
10787                 RSurf_DrawBatch();
10788         }
10789         else if (!r_refdef.view.showdebug)
10790         {
10791                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10792                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10793                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10794                 {
10795                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10796                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10797                 }
10798                 R_Mesh_PrepareVertices_Generic_Unlock();
10799                 RSurf_DrawBatch();
10800         }
10801         else if (r_showsurfaces.integer == 4)
10802         {
10803                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10804                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10805                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10806                 {
10807                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10808                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10809                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10810                 }
10811                 R_Mesh_PrepareVertices_Generic_Unlock();
10812                 RSurf_DrawBatch();
10813         }
10814         else if (r_showsurfaces.integer == 2)
10815         {
10816                 const int *e;
10817                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10818                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10819                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10820                 {
10821                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10822                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10823                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10824                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10825                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10826                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10827                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10828                 }
10829                 R_Mesh_PrepareVertices_Generic_Unlock();
10830                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10831         }
10832         else
10833         {
10834                 int texturesurfaceindex;
10835                 int k;
10836                 const msurface_t *surface;
10837                 float surfacecolor4f[4];
10838                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10839                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10840                 vi = 0;
10841                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10842                 {
10843                         surface = texturesurfacelist[texturesurfaceindex];
10844                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10845                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10846                         for (j = 0;j < surface->num_vertices;j++)
10847                         {
10848                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10849                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10850                                 vi++;
10851                         }
10852                 }
10853                 R_Mesh_PrepareVertices_Generic_Unlock();
10854                 RSurf_DrawBatch();
10855         }
10856 }
10857
10858 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10859 {
10860         CHECKGLERROR
10861         RSurf_SetupDepthAndCulling();
10862         if (r_showsurfaces.integer)
10863         {
10864                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10865                 return;
10866         }
10867         switch (vid.renderpath)
10868         {
10869         case RENDERPATH_GL20:
10870         case RENDERPATH_D3D9:
10871         case RENDERPATH_D3D10:
10872         case RENDERPATH_D3D11:
10873         case RENDERPATH_SOFT:
10874         case RENDERPATH_GLES2:
10875                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10876                 break;
10877         case RENDERPATH_GL13:
10878         case RENDERPATH_GLES1:
10879                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10880                 break;
10881         case RENDERPATH_GL11:
10882                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10883                 break;
10884         }
10885         CHECKGLERROR
10886 }
10887
10888 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10889 {
10890         CHECKGLERROR
10891         RSurf_SetupDepthAndCulling();
10892         if (r_showsurfaces.integer)
10893         {
10894                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10895                 return;
10896         }
10897         switch (vid.renderpath)
10898         {
10899         case RENDERPATH_GL20:
10900         case RENDERPATH_D3D9:
10901         case RENDERPATH_D3D10:
10902         case RENDERPATH_D3D11:
10903         case RENDERPATH_SOFT:
10904         case RENDERPATH_GLES2:
10905                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10906                 break;
10907         case RENDERPATH_GL13:
10908         case RENDERPATH_GLES1:
10909                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10910                 break;
10911         case RENDERPATH_GL11:
10912                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10913                 break;
10914         }
10915         CHECKGLERROR
10916 }
10917
10918 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10919 {
10920         int i, j;
10921         int texturenumsurfaces, endsurface;
10922         texture_t *texture;
10923         const msurface_t *surface;
10924         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10925
10926         // if the model is static it doesn't matter what value we give for
10927         // wantnormals and wanttangents, so this logic uses only rules applicable
10928         // to a model, knowing that they are meaningless otherwise
10929         if (ent == r_refdef.scene.worldentity)
10930                 RSurf_ActiveWorldEntity();
10931         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10932                 RSurf_ActiveModelEntity(ent, false, false, false);
10933         else
10934         {
10935                 switch (vid.renderpath)
10936                 {
10937                 case RENDERPATH_GL20:
10938                 case RENDERPATH_D3D9:
10939                 case RENDERPATH_D3D10:
10940                 case RENDERPATH_D3D11:
10941                 case RENDERPATH_SOFT:
10942                 case RENDERPATH_GLES2:
10943                         RSurf_ActiveModelEntity(ent, true, true, false);
10944                         break;
10945                 case RENDERPATH_GL11:
10946                 case RENDERPATH_GL13:
10947                 case RENDERPATH_GLES1:
10948                         RSurf_ActiveModelEntity(ent, true, false, false);
10949                         break;
10950                 }
10951         }
10952
10953         if (r_transparentdepthmasking.integer)
10954         {
10955                 qboolean setup = false;
10956                 for (i = 0;i < numsurfaces;i = j)
10957                 {
10958                         j = i + 1;
10959                         surface = rsurface.modelsurfaces + surfacelist[i];
10960                         texture = surface->texture;
10961                         rsurface.texture = R_GetCurrentTexture(texture);
10962                         rsurface.lightmaptexture = NULL;
10963                         rsurface.deluxemaptexture = NULL;
10964                         rsurface.uselightmaptexture = false;
10965                         // scan ahead until we find a different texture
10966                         endsurface = min(i + 1024, numsurfaces);
10967                         texturenumsurfaces = 0;
10968                         texturesurfacelist[texturenumsurfaces++] = surface;
10969                         for (;j < endsurface;j++)
10970                         {
10971                                 surface = rsurface.modelsurfaces + surfacelist[j];
10972                                 if (texture != surface->texture)
10973                                         break;
10974                                 texturesurfacelist[texturenumsurfaces++] = surface;
10975                         }
10976                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10977                                 continue;
10978                         // render the range of surfaces as depth
10979                         if (!setup)
10980                         {
10981                                 setup = true;
10982                                 GL_ColorMask(0,0,0,0);
10983                                 GL_Color(1,1,1,1);
10984                                 GL_DepthTest(true);
10985                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10986                                 GL_DepthMask(true);
10987 //                              R_Mesh_ResetTextureState();
10988                         }
10989                         RSurf_SetupDepthAndCulling();
10990                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10991                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
10992                         if (rsurface.batchvertex3fbuffer)
10993                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10994                         else
10995                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10996                         RSurf_DrawBatch();
10997                 }
10998                 if (setup)
10999                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11000         }
11001
11002         for (i = 0;i < numsurfaces;i = j)
11003         {
11004                 j = i + 1;
11005                 surface = rsurface.modelsurfaces + surfacelist[i];
11006                 texture = surface->texture;
11007                 rsurface.texture = R_GetCurrentTexture(texture);
11008                 // scan ahead until we find a different texture
11009                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11010                 texturenumsurfaces = 0;
11011                 texturesurfacelist[texturenumsurfaces++] = surface;
11012                 if(FAKELIGHT_ENABLED)
11013                 {
11014                         rsurface.lightmaptexture = NULL;
11015                         rsurface.deluxemaptexture = NULL;
11016                         rsurface.uselightmaptexture = false;
11017                         for (;j < endsurface;j++)
11018                         {
11019                                 surface = rsurface.modelsurfaces + surfacelist[j];
11020                                 if (texture != surface->texture)
11021                                         break;
11022                                 texturesurfacelist[texturenumsurfaces++] = surface;
11023                         }
11024                 }
11025                 else
11026                 {
11027                         rsurface.lightmaptexture = surface->lightmaptexture;
11028                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11029                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11030                         for (;j < endsurface;j++)
11031                         {
11032                                 surface = rsurface.modelsurfaces + surfacelist[j];
11033                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11034                                         break;
11035                                 texturesurfacelist[texturenumsurfaces++] = surface;
11036                         }
11037                 }
11038                 // render the range of surfaces
11039                 if (ent == r_refdef.scene.worldentity)
11040                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11041                 else
11042                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11043         }
11044         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11045 }
11046
11047 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11048 {
11049         // transparent surfaces get pushed off into the transparent queue
11050         int surfacelistindex;
11051         const msurface_t *surface;
11052         vec3_t tempcenter, center;
11053         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11054         {
11055                 surface = texturesurfacelist[surfacelistindex];
11056                 if (r_transparent_sortsurfacesbynearest.integer)
11057                 {
11058                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11059                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11060                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11061                 }
11062                 else
11063                 {
11064                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11065                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11066                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11067                 }
11068                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11069                 if (rsurface.entity->transparent_offset) // transparent offset
11070                 {
11071                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11072                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11073                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11074                 }
11075                 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);
11076         }
11077 }
11078
11079 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11080 {
11081         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11082                 return;
11083         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11084                 return;
11085         RSurf_SetupDepthAndCulling();
11086         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11087         if (rsurface.batchvertex3fbuffer)
11088                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
11089         else
11090                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
11091         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11092         RSurf_DrawBatch();
11093 }
11094
11095 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11096 {
11097         CHECKGLERROR
11098         if (depthonly)
11099                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11100         else if (prepass)
11101         {
11102                 if (!rsurface.texture->currentnumlayers)
11103                         return;
11104                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11105                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11106                 else
11107                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11108         }
11109         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11110                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11111         else if (!rsurface.texture->currentnumlayers)
11112                 return;
11113         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11114         {
11115                 // in the deferred case, transparent surfaces were queued during prepass
11116                 if (!r_shadow_usingdeferredprepass)
11117                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11118         }
11119         else
11120         {
11121                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11122                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11123         }
11124         CHECKGLERROR
11125 }
11126
11127 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11128 {
11129         int i, j;
11130         texture_t *texture;
11131         R_FrameData_SetMark();
11132         // break the surface list down into batches by texture and use of lightmapping
11133         for (i = 0;i < numsurfaces;i = j)
11134         {
11135                 j = i + 1;
11136                 // texture is the base texture pointer, rsurface.texture is the
11137                 // current frame/skin the texture is directing us to use (for example
11138                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11139                 // use skin 1 instead)
11140                 texture = surfacelist[i]->texture;
11141                 rsurface.texture = R_GetCurrentTexture(texture);
11142                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11143                 {
11144                         // if this texture is not the kind we want, skip ahead to the next one
11145                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11146                                 ;
11147                         continue;
11148                 }
11149                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11150                 {
11151                         rsurface.lightmaptexture = NULL;
11152                         rsurface.deluxemaptexture = NULL;
11153                         rsurface.uselightmaptexture = false;
11154                         // simply scan ahead until we find a different texture or lightmap state
11155                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11156                                 ;
11157                 }
11158                 else
11159                 {
11160                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11161                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11162                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11163                         // simply scan ahead until we find a different texture or lightmap state
11164                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11165                                 ;
11166                 }
11167                 // render the range of surfaces
11168                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11169         }
11170         R_FrameData_ReturnToMark();
11171 }
11172
11173 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11174 {
11175         CHECKGLERROR
11176         if (depthonly)
11177                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11178         else if (prepass)
11179         {
11180                 if (!rsurface.texture->currentnumlayers)
11181                         return;
11182                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11183                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11184                 else
11185                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11186         }
11187         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11188                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11189         else if (!rsurface.texture->currentnumlayers)
11190                 return;
11191         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11192         {
11193                 // in the deferred case, transparent surfaces were queued during prepass
11194                 if (!r_shadow_usingdeferredprepass)
11195                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11196         }
11197         else
11198         {
11199                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11200                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11201         }
11202         CHECKGLERROR
11203 }
11204
11205 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11206 {
11207         int i, j;
11208         texture_t *texture;
11209         R_FrameData_SetMark();
11210         // break the surface list down into batches by texture and use of lightmapping
11211         for (i = 0;i < numsurfaces;i = j)
11212         {
11213                 j = i + 1;
11214                 // texture is the base texture pointer, rsurface.texture is the
11215                 // current frame/skin the texture is directing us to use (for example
11216                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11217                 // use skin 1 instead)
11218                 texture = surfacelist[i]->texture;
11219                 rsurface.texture = R_GetCurrentTexture(texture);
11220                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11221                 {
11222                         // if this texture is not the kind we want, skip ahead to the next one
11223                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11224                                 ;
11225                         continue;
11226                 }
11227                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11228                 {
11229                         rsurface.lightmaptexture = NULL;
11230                         rsurface.deluxemaptexture = NULL;
11231                         rsurface.uselightmaptexture = false;
11232                         // simply scan ahead until we find a different texture or lightmap state
11233                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11234                                 ;
11235                 }
11236                 else
11237                 {
11238                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11239                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11240                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11241                         // simply scan ahead until we find a different texture or lightmap state
11242                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11243                                 ;
11244                 }
11245                 // render the range of surfaces
11246                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11247         }
11248         R_FrameData_ReturnToMark();
11249 }
11250
11251 float locboxvertex3f[6*4*3] =
11252 {
11253         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11254         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11255         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11256         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11257         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11258         1,0,0, 0,0,0, 0,1,0, 1,1,0
11259 };
11260
11261 unsigned short locboxelements[6*2*3] =
11262 {
11263          0, 1, 2, 0, 2, 3,
11264          4, 5, 6, 4, 6, 7,
11265          8, 9,10, 8,10,11,
11266         12,13,14, 12,14,15,
11267         16,17,18, 16,18,19,
11268         20,21,22, 20,22,23
11269 };
11270
11271 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11272 {
11273         int i, j;
11274         cl_locnode_t *loc = (cl_locnode_t *)ent;
11275         vec3_t mins, size;
11276         float vertex3f[6*4*3];
11277         CHECKGLERROR
11278         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11279         GL_DepthMask(false);
11280         GL_DepthRange(0, 1);
11281         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11282         GL_DepthTest(true);
11283         GL_CullFace(GL_NONE);
11284         R_EntityMatrix(&identitymatrix);
11285
11286 //      R_Mesh_ResetTextureState();
11287
11288         i = surfacelist[0];
11289         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11290                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11291                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11292                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11293
11294         if (VectorCompare(loc->mins, loc->maxs))
11295         {
11296                 VectorSet(size, 2, 2, 2);
11297                 VectorMA(loc->mins, -0.5f, size, mins);
11298         }
11299         else
11300         {
11301                 VectorCopy(loc->mins, mins);
11302                 VectorSubtract(loc->maxs, loc->mins, size);
11303         }
11304
11305         for (i = 0;i < 6*4*3;)
11306                 for (j = 0;j < 3;j++, i++)
11307                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11308
11309         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11310         R_SetupShader_Generic_NoTexture(false, false);
11311         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11312 }
11313
11314 void R_DrawLocs(void)
11315 {
11316         int index;
11317         cl_locnode_t *loc, *nearestloc;
11318         vec3_t center;
11319         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11320         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11321         {
11322                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11323                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11324         }
11325 }
11326
11327 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11328 {
11329         if (decalsystem->decals)
11330                 Mem_Free(decalsystem->decals);
11331         memset(decalsystem, 0, sizeof(*decalsystem));
11332 }
11333
11334 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)
11335 {
11336         tridecal_t *decal;
11337         tridecal_t *decals;
11338         int i;
11339
11340         // expand or initialize the system
11341         if (decalsystem->maxdecals <= decalsystem->numdecals)
11342         {
11343                 decalsystem_t old = *decalsystem;
11344                 qboolean useshortelements;
11345                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11346                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11347                 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)));
11348                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11349                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11350                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11351                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11352                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11353                 if (decalsystem->numdecals)
11354                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11355                 if (old.decals)
11356                         Mem_Free(old.decals);
11357                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11358                         decalsystem->element3i[i] = i;
11359                 if (useshortelements)
11360                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11361                                 decalsystem->element3s[i] = i;
11362         }
11363
11364         // grab a decal and search for another free slot for the next one
11365         decals = decalsystem->decals;
11366         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11367         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11368                 ;
11369         decalsystem->freedecal = i;
11370         if (decalsystem->numdecals <= i)
11371                 decalsystem->numdecals = i + 1;
11372
11373         // initialize the decal
11374         decal->lived = 0;
11375         decal->triangleindex = triangleindex;
11376         decal->surfaceindex = surfaceindex;
11377         decal->decalsequence = decalsequence;
11378         decal->color4f[0][0] = c0[0];
11379         decal->color4f[0][1] = c0[1];
11380         decal->color4f[0][2] = c0[2];
11381         decal->color4f[0][3] = 1;
11382         decal->color4f[1][0] = c1[0];
11383         decal->color4f[1][1] = c1[1];
11384         decal->color4f[1][2] = c1[2];
11385         decal->color4f[1][3] = 1;
11386         decal->color4f[2][0] = c2[0];
11387         decal->color4f[2][1] = c2[1];
11388         decal->color4f[2][2] = c2[2];
11389         decal->color4f[2][3] = 1;
11390         decal->vertex3f[0][0] = v0[0];
11391         decal->vertex3f[0][1] = v0[1];
11392         decal->vertex3f[0][2] = v0[2];
11393         decal->vertex3f[1][0] = v1[0];
11394         decal->vertex3f[1][1] = v1[1];
11395         decal->vertex3f[1][2] = v1[2];
11396         decal->vertex3f[2][0] = v2[0];
11397         decal->vertex3f[2][1] = v2[1];
11398         decal->vertex3f[2][2] = v2[2];
11399         decal->texcoord2f[0][0] = t0[0];
11400         decal->texcoord2f[0][1] = t0[1];
11401         decal->texcoord2f[1][0] = t1[0];
11402         decal->texcoord2f[1][1] = t1[1];
11403         decal->texcoord2f[2][0] = t2[0];
11404         decal->texcoord2f[2][1] = t2[1];
11405         TriangleNormal(v0, v1, v2, decal->plane);
11406         VectorNormalize(decal->plane);
11407         decal->plane[3] = DotProduct(v0, decal->plane);
11408 }
11409
11410 extern cvar_t cl_decals_bias;
11411 extern cvar_t cl_decals_models;
11412 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11413 // baseparms, parms, temps
11414 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)
11415 {
11416         int cornerindex;
11417         int index;
11418         float v[9][3];
11419         const float *vertex3f;
11420         const float *normal3f;
11421         int numpoints;
11422         float points[2][9][3];
11423         float temp[3];
11424         float tc[9][2];
11425         float f;
11426         float c[9][4];
11427         const int *e;
11428
11429         e = rsurface.modelelement3i + 3*triangleindex;
11430
11431         vertex3f = rsurface.modelvertex3f;
11432         normal3f = rsurface.modelnormal3f;
11433
11434         if (normal3f)
11435         {
11436                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11437                 {
11438                         index = 3*e[cornerindex];
11439                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11440                 }
11441         }
11442         else
11443         {
11444                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11445                 {
11446                         index = 3*e[cornerindex];
11447                         VectorCopy(vertex3f + index, v[cornerindex]);
11448                 }
11449         }
11450
11451         // cull backfaces
11452         //TriangleNormal(v[0], v[1], v[2], normal);
11453         //if (DotProduct(normal, localnormal) < 0.0f)
11454         //      continue;
11455         // clip by each of the box planes formed from the projection matrix
11456         // if anything survives, we emit the decal
11457         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]);
11458         if (numpoints < 3)
11459                 return;
11460         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]);
11461         if (numpoints < 3)
11462                 return;
11463         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]);
11464         if (numpoints < 3)
11465                 return;
11466         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]);
11467         if (numpoints < 3)
11468                 return;
11469         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]);
11470         if (numpoints < 3)
11471                 return;
11472         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]);
11473         if (numpoints < 3)
11474                 return;
11475         // some part of the triangle survived, so we have to accept it...
11476         if (dynamic)
11477         {
11478                 // dynamic always uses the original triangle
11479                 numpoints = 3;
11480                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11481                 {
11482                         index = 3*e[cornerindex];
11483                         VectorCopy(vertex3f + index, v[cornerindex]);
11484                 }
11485         }
11486         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11487         {
11488                 // convert vertex positions to texcoords
11489                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11490                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11491                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11492                 // calculate distance fade from the projection origin
11493                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11494                 f = bound(0.0f, f, 1.0f);
11495                 c[cornerindex][0] = r * f;
11496                 c[cornerindex][1] = g * f;
11497                 c[cornerindex][2] = b * f;
11498                 c[cornerindex][3] = 1.0f;
11499                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11500         }
11501         if (dynamic)
11502                 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);
11503         else
11504                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11505                         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);
11506 }
11507 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)
11508 {
11509         matrix4x4_t projection;
11510         decalsystem_t *decalsystem;
11511         qboolean dynamic;
11512         dp_model_t *model;
11513         const msurface_t *surface;
11514         const msurface_t *surfaces;
11515         const int *surfacelist;
11516         const texture_t *texture;
11517         int numtriangles;
11518         int numsurfacelist;
11519         int surfacelistindex;
11520         int surfaceindex;
11521         int triangleindex;
11522         float localorigin[3];
11523         float localnormal[3];
11524         float localmins[3];
11525         float localmaxs[3];
11526         float localsize;
11527         //float normal[3];
11528         float planes[6][4];
11529         float angles[3];
11530         bih_t *bih;
11531         int bih_triangles_count;
11532         int bih_triangles[256];
11533         int bih_surfaces[256];
11534
11535         decalsystem = &ent->decalsystem;
11536         model = ent->model;
11537         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11538         {
11539                 R_DecalSystem_Reset(&ent->decalsystem);
11540                 return;
11541         }
11542
11543         if (!model->brush.data_leafs && !cl_decals_models.integer)
11544         {
11545                 if (decalsystem->model)
11546                         R_DecalSystem_Reset(decalsystem);
11547                 return;
11548         }
11549
11550         if (decalsystem->model != model)
11551                 R_DecalSystem_Reset(decalsystem);
11552         decalsystem->model = model;
11553
11554         RSurf_ActiveModelEntity(ent, true, false, false);
11555
11556         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11557         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11558         VectorNormalize(localnormal);
11559         localsize = worldsize*rsurface.inversematrixscale;
11560         localmins[0] = localorigin[0] - localsize;
11561         localmins[1] = localorigin[1] - localsize;
11562         localmins[2] = localorigin[2] - localsize;
11563         localmaxs[0] = localorigin[0] + localsize;
11564         localmaxs[1] = localorigin[1] + localsize;
11565         localmaxs[2] = localorigin[2] + localsize;
11566
11567         //VectorCopy(localnormal, planes[4]);
11568         //VectorVectors(planes[4], planes[2], planes[0]);
11569         AnglesFromVectors(angles, localnormal, NULL, false);
11570         AngleVectors(angles, planes[0], planes[2], planes[4]);
11571         VectorNegate(planes[0], planes[1]);
11572         VectorNegate(planes[2], planes[3]);
11573         VectorNegate(planes[4], planes[5]);
11574         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11575         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11576         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11577         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11578         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11579         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11580
11581 #if 1
11582 // works
11583 {
11584         matrix4x4_t forwardprojection;
11585         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11586         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11587 }
11588 #else
11589 // broken
11590 {
11591         float projectionvector[4][3];
11592         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11593         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11594         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11595         projectionvector[0][0] = planes[0][0] * ilocalsize;
11596         projectionvector[0][1] = planes[1][0] * ilocalsize;
11597         projectionvector[0][2] = planes[2][0] * ilocalsize;
11598         projectionvector[1][0] = planes[0][1] * ilocalsize;
11599         projectionvector[1][1] = planes[1][1] * ilocalsize;
11600         projectionvector[1][2] = planes[2][1] * ilocalsize;
11601         projectionvector[2][0] = planes[0][2] * ilocalsize;
11602         projectionvector[2][1] = planes[1][2] * ilocalsize;
11603         projectionvector[2][2] = planes[2][2] * ilocalsize;
11604         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11605         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11606         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11607         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11608 }
11609 #endif
11610
11611         dynamic = model->surfmesh.isanimated;
11612         numsurfacelist = model->nummodelsurfaces;
11613         surfacelist = model->sortedmodelsurfaces;
11614         surfaces = model->data_surfaces;
11615
11616         bih = NULL;
11617         bih_triangles_count = -1;
11618         if(!dynamic)
11619         {
11620                 if(model->render_bih.numleafs)
11621                         bih = &model->render_bih;
11622                 else if(model->collision_bih.numleafs)
11623                         bih = &model->collision_bih;
11624         }
11625         if(bih)
11626                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11627         if(bih_triangles_count == 0)
11628                 return;
11629         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11630                 return;
11631         if(bih_triangles_count > 0)
11632         {
11633                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11634                 {
11635                         surfaceindex = bih_surfaces[triangleindex];
11636                         surface = surfaces + surfaceindex;
11637                         texture = surface->texture;
11638                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11639                                 continue;
11640                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11641                                 continue;
11642                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11643                 }
11644         }
11645         else
11646         {
11647                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11648                 {
11649                         surfaceindex = surfacelist[surfacelistindex];
11650                         surface = surfaces + surfaceindex;
11651                         // check cull box first because it rejects more than any other check
11652                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11653                                 continue;
11654                         // skip transparent surfaces
11655                         texture = surface->texture;
11656                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11657                                 continue;
11658                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11659                                 continue;
11660                         numtriangles = surface->num_triangles;
11661                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11662                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11663                 }
11664         }
11665 }
11666
11667 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11668 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)
11669 {
11670         int renderentityindex;
11671         float worldmins[3];
11672         float worldmaxs[3];
11673         entity_render_t *ent;
11674
11675         if (!cl_decals_newsystem.integer)
11676                 return;
11677
11678         worldmins[0] = worldorigin[0] - worldsize;
11679         worldmins[1] = worldorigin[1] - worldsize;
11680         worldmins[2] = worldorigin[2] - worldsize;
11681         worldmaxs[0] = worldorigin[0] + worldsize;
11682         worldmaxs[1] = worldorigin[1] + worldsize;
11683         worldmaxs[2] = worldorigin[2] + worldsize;
11684
11685         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11686
11687         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11688         {
11689                 ent = r_refdef.scene.entities[renderentityindex];
11690                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11691                         continue;
11692
11693                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11694         }
11695 }
11696
11697 typedef struct r_decalsystem_splatqueue_s
11698 {
11699         vec3_t worldorigin;
11700         vec3_t worldnormal;
11701         float color[4];
11702         float tcrange[4];
11703         float worldsize;
11704         int decalsequence;
11705 }
11706 r_decalsystem_splatqueue_t;
11707
11708 int r_decalsystem_numqueued = 0;
11709 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11710
11711 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)
11712 {
11713         r_decalsystem_splatqueue_t *queue;
11714
11715         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11716                 return;
11717
11718         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11719         VectorCopy(worldorigin, queue->worldorigin);
11720         VectorCopy(worldnormal, queue->worldnormal);
11721         Vector4Set(queue->color, r, g, b, a);
11722         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11723         queue->worldsize = worldsize;
11724         queue->decalsequence = cl.decalsequence++;
11725 }
11726
11727 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11728 {
11729         int i;
11730         r_decalsystem_splatqueue_t *queue;
11731
11732         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11733                 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);
11734         r_decalsystem_numqueued = 0;
11735 }
11736
11737 extern cvar_t cl_decals_max;
11738 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11739 {
11740         int i;
11741         decalsystem_t *decalsystem = &ent->decalsystem;
11742         int numdecals;
11743         int killsequence;
11744         tridecal_t *decal;
11745         float frametime;
11746         float lifetime;
11747
11748         if (!decalsystem->numdecals)
11749                 return;
11750
11751         if (r_showsurfaces.integer)
11752                 return;
11753
11754         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11755         {
11756                 R_DecalSystem_Reset(decalsystem);
11757                 return;
11758         }
11759
11760         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11761         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11762
11763         if (decalsystem->lastupdatetime)
11764                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11765         else
11766                 frametime = 0;
11767         decalsystem->lastupdatetime = r_refdef.scene.time;
11768         numdecals = decalsystem->numdecals;
11769
11770         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11771         {
11772                 if (decal->color4f[0][3])
11773                 {
11774                         decal->lived += frametime;
11775                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11776                         {
11777                                 memset(decal, 0, sizeof(*decal));
11778                                 if (decalsystem->freedecal > i)
11779                                         decalsystem->freedecal = i;
11780                         }
11781                 }
11782         }
11783         decal = decalsystem->decals;
11784         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11785                 numdecals--;
11786
11787         // collapse the array by shuffling the tail decals into the gaps
11788         for (;;)
11789         {
11790                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11791                         decalsystem->freedecal++;
11792                 if (decalsystem->freedecal == numdecals)
11793                         break;
11794                 decal[decalsystem->freedecal] = decal[--numdecals];
11795         }
11796
11797         decalsystem->numdecals = numdecals;
11798
11799         if (numdecals <= 0)
11800         {
11801                 // if there are no decals left, reset decalsystem
11802                 R_DecalSystem_Reset(decalsystem);
11803         }
11804 }
11805
11806 extern skinframe_t *decalskinframe;
11807 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11808 {
11809         int i;
11810         decalsystem_t *decalsystem = &ent->decalsystem;
11811         int numdecals;
11812         tridecal_t *decal;
11813         float faderate;
11814         float alpha;
11815         float *v3f;
11816         float *c4f;
11817         float *t2f;
11818         const int *e;
11819         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11820         int numtris = 0;
11821
11822         numdecals = decalsystem->numdecals;
11823         if (!numdecals)
11824                 return;
11825
11826         if (r_showsurfaces.integer)
11827                 return;
11828
11829         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11830         {
11831                 R_DecalSystem_Reset(decalsystem);
11832                 return;
11833         }
11834
11835         // if the model is static it doesn't matter what value we give for
11836         // wantnormals and wanttangents, so this logic uses only rules applicable
11837         // to a model, knowing that they are meaningless otherwise
11838         if (ent == r_refdef.scene.worldentity)
11839                 RSurf_ActiveWorldEntity();
11840         else
11841                 RSurf_ActiveModelEntity(ent, false, false, false);
11842
11843         decalsystem->lastupdatetime = r_refdef.scene.time;
11844
11845         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11846
11847         // update vertex positions for animated models
11848         v3f = decalsystem->vertex3f;
11849         c4f = decalsystem->color4f;
11850         t2f = decalsystem->texcoord2f;
11851         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11852         {
11853                 if (!decal->color4f[0][3])
11854                         continue;
11855
11856                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11857                         continue;
11858
11859                 // skip backfaces
11860                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11861                         continue;
11862
11863                 // update color values for fading decals
11864                 if (decal->lived >= cl_decals_time.value)
11865                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11866                 else
11867                         alpha = 1.0f;
11868
11869                 c4f[ 0] = decal->color4f[0][0] * alpha;
11870                 c4f[ 1] = decal->color4f[0][1] * alpha;
11871                 c4f[ 2] = decal->color4f[0][2] * alpha;
11872                 c4f[ 3] = 1;
11873                 c4f[ 4] = decal->color4f[1][0] * alpha;
11874                 c4f[ 5] = decal->color4f[1][1] * alpha;
11875                 c4f[ 6] = decal->color4f[1][2] * alpha;
11876                 c4f[ 7] = 1;
11877                 c4f[ 8] = decal->color4f[2][0] * alpha;
11878                 c4f[ 9] = decal->color4f[2][1] * alpha;
11879                 c4f[10] = decal->color4f[2][2] * alpha;
11880                 c4f[11] = 1;
11881
11882                 t2f[0] = decal->texcoord2f[0][0];
11883                 t2f[1] = decal->texcoord2f[0][1];
11884                 t2f[2] = decal->texcoord2f[1][0];
11885                 t2f[3] = decal->texcoord2f[1][1];
11886                 t2f[4] = decal->texcoord2f[2][0];
11887                 t2f[5] = decal->texcoord2f[2][1];
11888
11889                 // update vertex positions for animated models
11890                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11891                 {
11892                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11893                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11894                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11895                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11896                 }
11897                 else
11898                 {
11899                         VectorCopy(decal->vertex3f[0], v3f);
11900                         VectorCopy(decal->vertex3f[1], v3f + 3);
11901                         VectorCopy(decal->vertex3f[2], v3f + 6);
11902                 }
11903
11904                 if (r_refdef.fogenabled)
11905                 {
11906                         alpha = RSurf_FogVertex(v3f);
11907                         VectorScale(c4f, alpha, c4f);
11908                         alpha = RSurf_FogVertex(v3f + 3);
11909                         VectorScale(c4f + 4, alpha, c4f + 4);
11910                         alpha = RSurf_FogVertex(v3f + 6);
11911                         VectorScale(c4f + 8, alpha, c4f + 8);
11912                 }
11913
11914                 v3f += 9;
11915                 c4f += 12;
11916                 t2f += 6;
11917                 numtris++;
11918         }
11919
11920         if (numtris > 0)
11921         {
11922                 r_refdef.stats[r_stat_drawndecals] += numtris;
11923
11924                 // now render the decals all at once
11925                 // (this assumes they all use one particle font texture!)
11926                 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);
11927 //              R_Mesh_ResetTextureState();
11928                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11929                 GL_DepthMask(false);
11930                 GL_DepthRange(0, 1);
11931                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11932                 GL_DepthTest(true);
11933                 GL_CullFace(GL_NONE);
11934                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11935                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11936                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11937         }
11938 }
11939
11940 static void R_DrawModelDecals(void)
11941 {
11942         int i, numdecals;
11943
11944         // fade faster when there are too many decals
11945         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11946         for (i = 0;i < r_refdef.scene.numentities;i++)
11947                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11948
11949         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11950         for (i = 0;i < r_refdef.scene.numentities;i++)
11951                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11952                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11953
11954         R_DecalSystem_ApplySplatEntitiesQueue();
11955
11956         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11957         for (i = 0;i < r_refdef.scene.numentities;i++)
11958                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11959
11960         r_refdef.stats[r_stat_totaldecals] += numdecals;
11961
11962         if (r_showsurfaces.integer)
11963                 return;
11964
11965         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11966
11967         for (i = 0;i < r_refdef.scene.numentities;i++)
11968         {
11969                 if (!r_refdef.viewcache.entityvisible[i])
11970                         continue;
11971                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11972                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11973         }
11974 }
11975
11976 extern cvar_t mod_collision_bih;
11977 static void R_DrawDebugModel(void)
11978 {
11979         entity_render_t *ent = rsurface.entity;
11980         int i, j, k, l, flagsmask;
11981         const msurface_t *surface;
11982         dp_model_t *model = ent->model;
11983         vec3_t v;
11984
11985         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11986                 return;
11987
11988         if (r_showoverdraw.value > 0)
11989         {
11990                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11991                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11992                 R_SetupShader_Generic_NoTexture(false, false);
11993                 GL_DepthTest(false);
11994                 GL_DepthMask(false);
11995                 GL_DepthRange(0, 1);
11996                 GL_BlendFunc(GL_ONE, GL_ONE);
11997                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11998                 {
11999                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12000                                 continue;
12001                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12002                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12003                         {
12004                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12005                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12006                                 if (!rsurface.texture->currentlayers->depthmask)
12007                                         GL_Color(c, 0, 0, 1.0f);
12008                                 else if (ent == r_refdef.scene.worldentity)
12009                                         GL_Color(c, c, c, 1.0f);
12010                                 else
12011                                         GL_Color(0, c, 0, 1.0f);
12012                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12013                                 RSurf_DrawBatch();
12014                         }
12015                 }
12016                 rsurface.texture = NULL;
12017         }
12018
12019         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12020
12021 //      R_Mesh_ResetTextureState();
12022         R_SetupShader_Generic_NoTexture(false, false);
12023         GL_DepthRange(0, 1);
12024         GL_DepthTest(!r_showdisabledepthtest.integer);
12025         GL_DepthMask(false);
12026         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12027
12028         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12029         {
12030                 int triangleindex;
12031                 int bihleafindex;
12032                 qboolean cullbox = false;
12033                 const q3mbrush_t *brush;
12034                 const bih_t *bih = &model->collision_bih;
12035                 const bih_leaf_t *bihleaf;
12036                 float vertex3f[3][3];
12037                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12038                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12039                 {
12040                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12041                                 continue;
12042                         switch (bihleaf->type)
12043                         {
12044                         case BIH_BRUSH:
12045                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12046                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12047                                 {
12048                                         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);
12049                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12050                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12051                                 }
12052                                 break;
12053                         case BIH_COLLISIONTRIANGLE:
12054                                 triangleindex = bihleaf->itemindex;
12055                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12056                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12057                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12058                                 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);
12059                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12060                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12061                                 break;
12062                         case BIH_RENDERTRIANGLE:
12063                                 triangleindex = bihleaf->itemindex;
12064                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12065                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12066                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12067                                 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);
12068                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12069                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12070                                 break;
12071                         }
12072                 }
12073         }
12074
12075         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12076
12077 #ifndef USE_GLES2
12078         if (r_showtris.integer && qglPolygonMode)
12079         {
12080                 if (r_showdisabledepthtest.integer)
12081                 {
12082                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12083                         GL_DepthMask(false);
12084                 }
12085                 else
12086                 {
12087                         GL_BlendFunc(GL_ONE, GL_ZERO);
12088                         GL_DepthMask(true);
12089                 }
12090                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12091                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12092                 {
12093                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12094                                 continue;
12095                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12096                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12097                         {
12098                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12099                                 if (!rsurface.texture->currentlayers->depthmask)
12100                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12101                                 else if (ent == r_refdef.scene.worldentity)
12102                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12103                                 else
12104                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12105                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12106                                 RSurf_DrawBatch();
12107                         }
12108                 }
12109                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12110                 rsurface.texture = NULL;
12111         }
12112
12113         if (r_shownormals.value != 0 && qglBegin)
12114         {
12115                 if (r_showdisabledepthtest.integer)
12116                 {
12117                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12118                         GL_DepthMask(false);
12119                 }
12120                 else
12121                 {
12122                         GL_BlendFunc(GL_ONE, GL_ZERO);
12123                         GL_DepthMask(true);
12124                 }
12125                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12126                 {
12127                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12128                                 continue;
12129                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12130                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12131                         {
12132                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12133                                 qglBegin(GL_LINES);
12134                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12135                                 {
12136                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12137                                         {
12138                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12139                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12140                                                 qglVertex3f(v[0], v[1], v[2]);
12141                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12142                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12143                                                 qglVertex3f(v[0], v[1], v[2]);
12144                                         }
12145                                 }
12146                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12147                                 {
12148                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12149                                         {
12150                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12151                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12152                                                 qglVertex3f(v[0], v[1], v[2]);
12153                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12154                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12155                                                 qglVertex3f(v[0], v[1], v[2]);
12156                                         }
12157                                 }
12158                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12159                                 {
12160                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12161                                         {
12162                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12163                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12164                                                 qglVertex3f(v[0], v[1], v[2]);
12165                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12166                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12167                                                 qglVertex3f(v[0], v[1], v[2]);
12168                                         }
12169                                 }
12170                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12171                                 {
12172                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12173                                         {
12174                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12175                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12176                                                 qglVertex3f(v[0], v[1], v[2]);
12177                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12178                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12179                                                 qglVertex3f(v[0], v[1], v[2]);
12180                                         }
12181                                 }
12182                                 qglEnd();
12183                                 CHECKGLERROR
12184                         }
12185                 }
12186                 rsurface.texture = NULL;
12187         }
12188 #endif
12189 }
12190
12191 int r_maxsurfacelist = 0;
12192 const msurface_t **r_surfacelist = NULL;
12193 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12194 {
12195         int i, j, endj, flagsmask;
12196         dp_model_t *model = r_refdef.scene.worldmodel;
12197         msurface_t *surfaces;
12198         unsigned char *update;
12199         int numsurfacelist = 0;
12200         if (model == NULL)
12201                 return;
12202
12203         if (r_maxsurfacelist < model->num_surfaces)
12204         {
12205                 r_maxsurfacelist = model->num_surfaces;
12206                 if (r_surfacelist)
12207                         Mem_Free((msurface_t**)r_surfacelist);
12208                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12209         }
12210
12211         RSurf_ActiveWorldEntity();
12212
12213         surfaces = model->data_surfaces;
12214         update = model->brushq1.lightmapupdateflags;
12215
12216         // update light styles on this submodel
12217         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12218         {
12219                 model_brush_lightstyleinfo_t *style;
12220                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12221                 {
12222                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12223                         {
12224                                 int *list = style->surfacelist;
12225                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12226                                 for (j = 0;j < style->numsurfaces;j++)
12227                                         update[list[j]] = true;
12228                         }
12229                 }
12230         }
12231
12232         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12233
12234         if (debug)
12235         {
12236                 R_DrawDebugModel();
12237                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12238                 return;
12239         }
12240
12241         rsurface.lightmaptexture = NULL;
12242         rsurface.deluxemaptexture = NULL;
12243         rsurface.uselightmaptexture = false;
12244         rsurface.texture = NULL;
12245         rsurface.rtlight = NULL;
12246         numsurfacelist = 0;
12247         // add visible surfaces to draw list
12248         for (i = 0;i < model->nummodelsurfaces;i++)
12249         {
12250                 j = model->sortedmodelsurfaces[i];
12251                 if (r_refdef.viewcache.world_surfacevisible[j])
12252                         r_surfacelist[numsurfacelist++] = surfaces + j;
12253         }
12254         // update lightmaps if needed
12255         if (model->brushq1.firstrender)
12256         {
12257                 model->brushq1.firstrender = false;
12258                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12259                         if (update[j])
12260                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12261         }
12262         else if (update)
12263         {
12264                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12265                         if (r_refdef.viewcache.world_surfacevisible[j])
12266                                 if (update[j])
12267                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12268         }
12269         // don't do anything if there were no surfaces
12270         if (!numsurfacelist)
12271         {
12272                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12273                 return;
12274         }
12275         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12276
12277         // add to stats if desired
12278         if (r_speeds.integer && !skysurfaces && !depthonly)
12279         {
12280                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12281                 for (j = 0;j < numsurfacelist;j++)
12282                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12283         }
12284
12285         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12286 }
12287
12288 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12289 {
12290         int i, j, endj, flagsmask;
12291         dp_model_t *model = ent->model;
12292         msurface_t *surfaces;
12293         unsigned char *update;
12294         int numsurfacelist = 0;
12295         if (model == NULL)
12296                 return;
12297
12298         if (r_maxsurfacelist < model->num_surfaces)
12299         {
12300                 r_maxsurfacelist = model->num_surfaces;
12301                 if (r_surfacelist)
12302                         Mem_Free((msurface_t **)r_surfacelist);
12303                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12304         }
12305
12306         // if the model is static it doesn't matter what value we give for
12307         // wantnormals and wanttangents, so this logic uses only rules applicable
12308         // to a model, knowing that they are meaningless otherwise
12309         if (ent == r_refdef.scene.worldentity)
12310                 RSurf_ActiveWorldEntity();
12311         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12312                 RSurf_ActiveModelEntity(ent, false, false, false);
12313         else if (prepass)
12314                 RSurf_ActiveModelEntity(ent, true, true, true);
12315         else if (depthonly)
12316         {
12317                 switch (vid.renderpath)
12318                 {
12319                 case RENDERPATH_GL20:
12320                 case RENDERPATH_D3D9:
12321                 case RENDERPATH_D3D10:
12322                 case RENDERPATH_D3D11:
12323                 case RENDERPATH_SOFT:
12324                 case RENDERPATH_GLES2:
12325                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12326                         break;
12327                 case RENDERPATH_GL11:
12328                 case RENDERPATH_GL13:
12329                 case RENDERPATH_GLES1:
12330                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12331                         break;
12332                 }
12333         }
12334         else
12335         {
12336                 switch (vid.renderpath)
12337                 {
12338                 case RENDERPATH_GL20:
12339                 case RENDERPATH_D3D9:
12340                 case RENDERPATH_D3D10:
12341                 case RENDERPATH_D3D11:
12342                 case RENDERPATH_SOFT:
12343                 case RENDERPATH_GLES2:
12344                         RSurf_ActiveModelEntity(ent, true, true, false);
12345                         break;
12346                 case RENDERPATH_GL11:
12347                 case RENDERPATH_GL13:
12348                 case RENDERPATH_GLES1:
12349                         RSurf_ActiveModelEntity(ent, true, false, false);
12350                         break;
12351                 }
12352         }
12353
12354         surfaces = model->data_surfaces;
12355         update = model->brushq1.lightmapupdateflags;
12356
12357         // update light styles
12358         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12359         {
12360                 model_brush_lightstyleinfo_t *style;
12361                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12362                 {
12363                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12364                         {
12365                                 int *list = style->surfacelist;
12366                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12367                                 for (j = 0;j < style->numsurfaces;j++)
12368                                         update[list[j]] = true;
12369                         }
12370                 }
12371         }
12372
12373         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12374
12375         if (debug)
12376         {
12377                 R_DrawDebugModel();
12378                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12379                 return;
12380         }
12381
12382         rsurface.lightmaptexture = NULL;
12383         rsurface.deluxemaptexture = NULL;
12384         rsurface.uselightmaptexture = false;
12385         rsurface.texture = NULL;
12386         rsurface.rtlight = NULL;
12387         numsurfacelist = 0;
12388         // add visible surfaces to draw list
12389         for (i = 0;i < model->nummodelsurfaces;i++)
12390                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12391         // don't do anything if there were no surfaces
12392         if (!numsurfacelist)
12393         {
12394                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12395                 return;
12396         }
12397         // update lightmaps if needed
12398         if (update)
12399         {
12400                 int updated = 0;
12401                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12402                 {
12403                         if (update[j])
12404                         {
12405                                 updated++;
12406                                 R_BuildLightMap(ent, surfaces + j);
12407                         }
12408                 }
12409         }
12410
12411         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12412
12413         // add to stats if desired
12414         if (r_speeds.integer && !skysurfaces && !depthonly)
12415         {
12416                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12417                 for (j = 0;j < numsurfacelist;j++)
12418                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12419         }
12420
12421         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12422 }
12423
12424 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12425 {
12426         static texture_t texture;
12427         static msurface_t surface;
12428         const msurface_t *surfacelist = &surface;
12429
12430         // fake enough texture and surface state to render this geometry
12431
12432         texture.update_lastrenderframe = -1; // regenerate this texture
12433         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12434         texture.currentskinframe = skinframe;
12435         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12436         texture.offsetmapping = OFFSETMAPPING_OFF;
12437         texture.offsetscale = 1;
12438         texture.specularscalemod = 1;
12439         texture.specularpowermod = 1;
12440         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12441         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12442         // JUST GREP FOR "specularscalemod = 1".
12443
12444         surface.texture = &texture;
12445         surface.num_triangles = numtriangles;
12446         surface.num_firsttriangle = firsttriangle;
12447         surface.num_vertices = numvertices;
12448         surface.num_firstvertex = firstvertex;
12449
12450         // now render it
12451         rsurface.texture = R_GetCurrentTexture(surface.texture);
12452         rsurface.lightmaptexture = NULL;
12453         rsurface.deluxemaptexture = NULL;
12454         rsurface.uselightmaptexture = false;
12455         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12456 }
12457
12458 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)
12459 {
12460         static msurface_t surface;
12461         const msurface_t *surfacelist = &surface;
12462
12463         // fake enough texture and surface state to render this geometry
12464         surface.texture = texture;
12465         surface.num_triangles = numtriangles;
12466         surface.num_firsttriangle = firsttriangle;
12467         surface.num_vertices = numvertices;
12468         surface.num_firstvertex = firstvertex;
12469
12470         // now render it
12471         rsurface.texture = R_GetCurrentTexture(surface.texture);
12472         rsurface.lightmaptexture = NULL;
12473         rsurface.deluxemaptexture = NULL;
12474         rsurface.uselightmaptexture = false;
12475         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12476 }