]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
added entity caching stats in graph
[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                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1970                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1971                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1972                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1973                 break;
1974         case RENDERPATH_GL13:
1975         case RENDERPATH_GLES1:
1976                 R_Mesh_TexBind(0, first );
1977                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1978                 R_Mesh_TexBind(1, second);
1979                 if (second)
1980                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1981                 break;
1982         case RENDERPATH_GL11:
1983                 R_Mesh_TexBind(0, first );
1984                 break;
1985         case RENDERPATH_SOFT:
1986                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1987                 R_Mesh_TexBind(GL20TU_FIRST , first );
1988                 R_Mesh_TexBind(GL20TU_SECOND, second);
1989                 break;
1990         }
1991 }
1992
1993 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1994 {
1995         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1996 }
1997
1998 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
1999 {
2000         unsigned int permutation = 0;
2001         if (r_trippy.integer && !notrippy)
2002                 permutation |= SHADERPERMUTATION_TRIPPY;
2003         if (depthrgb)
2004                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2005         if (skeletal)
2006                 permutation |= SHADERPERMUTATION_SKELETAL;
2007
2008         if (vid.allowalphatocoverage)
2009                 GL_AlphaToCoverage(false);
2010         switch (vid.renderpath)
2011         {
2012         case RENDERPATH_D3D9:
2013 #ifdef SUPPORTD3D
2014                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2015 #endif
2016                 break;
2017         case RENDERPATH_D3D10:
2018                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2019                 break;
2020         case RENDERPATH_D3D11:
2021                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2022                 break;
2023         case RENDERPATH_GL20:
2024         case RENDERPATH_GLES2:
2025                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2026                 break;
2027         case RENDERPATH_GL13:
2028         case RENDERPATH_GLES1:
2029                 R_Mesh_TexBind(0, 0);
2030                 R_Mesh_TexBind(1, 0);
2031                 break;
2032         case RENDERPATH_GL11:
2033                 R_Mesh_TexBind(0, 0);
2034                 break;
2035         case RENDERPATH_SOFT:
2036                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2037                 break;
2038         }
2039 }
2040
2041 extern qboolean r_shadow_usingdeferredprepass;
2042 extern rtexture_t *r_shadow_attenuationgradienttexture;
2043 extern rtexture_t *r_shadow_attenuation2dtexture;
2044 extern rtexture_t *r_shadow_attenuation3dtexture;
2045 extern qboolean r_shadow_usingshadowmap2d;
2046 extern qboolean r_shadow_usingshadowmaportho;
2047 extern float r_shadow_shadowmap_texturescale[2];
2048 extern float r_shadow_shadowmap_parameters[4];
2049 extern qboolean r_shadow_shadowmapvsdct;
2050 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2051 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2052 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2053 extern matrix4x4_t r_shadow_shadowmapmatrix;
2054 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2055 extern int r_shadow_prepass_width;
2056 extern int r_shadow_prepass_height;
2057 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2058 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2059 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2060 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2061
2062 #define BLENDFUNC_ALLOWS_COLORMOD      1
2063 #define BLENDFUNC_ALLOWS_FOG           2
2064 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2065 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2066 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2067 static int R_BlendFuncFlags(int src, int dst)
2068 {
2069         int r = 0;
2070
2071         // a blendfunc allows colormod if:
2072         // a) it can never keep the destination pixel invariant, or
2073         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2074         // this is to prevent unintended side effects from colormod
2075
2076         // a blendfunc allows fog if:
2077         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2078         // this is to prevent unintended side effects from fog
2079
2080         // these checks are the output of fogeval.pl
2081
2082         r |= BLENDFUNC_ALLOWS_COLORMOD;
2083         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2084         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2085         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2086         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2087         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2088         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2089         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2090         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2091         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2092         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2093         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2094         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2095         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2096         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2097         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2098         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2100         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2101         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2102         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2103         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2104
2105         return r;
2106 }
2107
2108 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)
2109 {
2110         // select a permutation of the lighting shader appropriate to this
2111         // combination of texture, entity, light source, and fogging, only use the
2112         // minimum features necessary to avoid wasting rendering time in the
2113         // fragment shader on features that are not being used
2114         unsigned int permutation = 0;
2115         unsigned int mode = 0;
2116         int blendfuncflags;
2117         static float dummy_colormod[3] = {1, 1, 1};
2118         float *colormod = rsurface.colormod;
2119         float m16f[16];
2120         matrix4x4_t tempmatrix;
2121         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2122         if (r_trippy.integer && !notrippy)
2123                 permutation |= SHADERPERMUTATION_TRIPPY;
2124         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2125                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2126         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2127                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2128         if (rsurfacepass == RSURFPASS_BACKGROUND)
2129         {
2130                 // distorted background
2131                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2132                 {
2133                         mode = SHADERMODE_WATER;
2134                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2135                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2136                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2137                         {
2138                                 // this is the right thing to do for wateralpha
2139                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2140                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2141                         }
2142                         else
2143                         {
2144                                 // this is the right thing to do for entity alpha
2145                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2147                         }
2148                 }
2149                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2150                 {
2151                         mode = SHADERMODE_REFRACTION;
2152                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2153                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2154                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2155                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2156                 }
2157                 else
2158                 {
2159                         mode = SHADERMODE_GENERIC;
2160                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2161                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2162                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2163                 }
2164                 if (vid.allowalphatocoverage)
2165                         GL_AlphaToCoverage(false);
2166         }
2167         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2168         {
2169                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2170                 {
2171                         switch(rsurface.texture->offsetmapping)
2172                         {
2173                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2174                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2175                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2176                         case OFFSETMAPPING_OFF: break;
2177                         }
2178                 }
2179                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2180                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2181                 // normalmap (deferred prepass), may use alpha test on diffuse
2182                 mode = SHADERMODE_DEFERREDGEOMETRY;
2183                 GL_BlendFunc(GL_ONE, GL_ZERO);
2184                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2185                 if (vid.allowalphatocoverage)
2186                         GL_AlphaToCoverage(false);
2187         }
2188         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2189         {
2190                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2191                 {
2192                         switch(rsurface.texture->offsetmapping)
2193                         {
2194                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2195                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2196                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2197                         case OFFSETMAPPING_OFF: break;
2198                         }
2199                 }
2200                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2201                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2202                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2203                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2204                 // light source
2205                 mode = SHADERMODE_LIGHTSOURCE;
2206                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2207                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2208                 if (diffusescale > 0)
2209                         permutation |= SHADERPERMUTATION_DIFFUSE;
2210                 if (specularscale > 0)
2211                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2212                 if (r_refdef.fogenabled)
2213                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2214                 if (rsurface.texture->colormapping)
2215                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2216                 if (r_shadow_usingshadowmap2d)
2217                 {
2218                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2219                         if(r_shadow_shadowmapvsdct)
2220                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2221
2222                         if (r_shadow_shadowmap2ddepthbuffer)
2223                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2224                 }
2225                 if (rsurface.texture->reflectmasktexture)
2226                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2227                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2228                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2229                 if (vid.allowalphatocoverage)
2230                         GL_AlphaToCoverage(false);
2231         }
2232         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2233         {
2234                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2235                 {
2236                         switch(rsurface.texture->offsetmapping)
2237                         {
2238                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2239                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2240                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2241                         case OFFSETMAPPING_OFF: break;
2242                         }
2243                 }
2244                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2245                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2246                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2247                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2248                 // unshaded geometry (fullbright or ambient model lighting)
2249                 mode = SHADERMODE_FLATCOLOR;
2250                 ambientscale = diffusescale = specularscale = 0;
2251                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2252                         permutation |= SHADERPERMUTATION_GLOW;
2253                 if (r_refdef.fogenabled)
2254                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2255                 if (rsurface.texture->colormapping)
2256                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2257                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2258                 {
2259                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2260                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2261
2262                         if (r_shadow_shadowmap2ddepthbuffer)
2263                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2264                 }
2265                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2266                         permutation |= SHADERPERMUTATION_REFLECTION;
2267                 if (rsurface.texture->reflectmasktexture)
2268                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2269                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2270                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2271                 // when using alphatocoverage, we don't need alphakill
2272                 if (vid.allowalphatocoverage)
2273                 {
2274                         if (r_transparent_alphatocoverage.integer)
2275                         {
2276                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2277                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2278                         }
2279                         else
2280                                 GL_AlphaToCoverage(false);
2281                 }
2282         }
2283         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2284         {
2285                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2286                 {
2287                         switch(rsurface.texture->offsetmapping)
2288                         {
2289                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2290                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2291                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2292                         case OFFSETMAPPING_OFF: break;
2293                         }
2294                 }
2295                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2296                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2297                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2298                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2299                 // directional model lighting
2300                 mode = SHADERMODE_LIGHTDIRECTION;
2301                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2302                         permutation |= SHADERPERMUTATION_GLOW;
2303                 permutation |= SHADERPERMUTATION_DIFFUSE;
2304                 if (specularscale > 0)
2305                         permutation |= SHADERPERMUTATION_SPECULAR;
2306                 if (r_refdef.fogenabled)
2307                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2308                 if (rsurface.texture->colormapping)
2309                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2310                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2311                 {
2312                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2313                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2314
2315                         if (r_shadow_shadowmap2ddepthbuffer)
2316                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2317                 }
2318                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2319                         permutation |= SHADERPERMUTATION_REFLECTION;
2320                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2321                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2322                 if (rsurface.texture->reflectmasktexture)
2323                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2324                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2325                 {
2326                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2327                         if (r_shadow_bouncegriddirectional)
2328                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2329                 }
2330                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2331                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2332                 // when using alphatocoverage, we don't need alphakill
2333                 if (vid.allowalphatocoverage)
2334                 {
2335                         if (r_transparent_alphatocoverage.integer)
2336                         {
2337                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2338                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2339                         }
2340                         else
2341                                 GL_AlphaToCoverage(false);
2342                 }
2343         }
2344         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2345         {
2346                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2347                 {
2348                         switch(rsurface.texture->offsetmapping)
2349                         {
2350                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2351                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2352                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2353                         case OFFSETMAPPING_OFF: break;
2354                         }
2355                 }
2356                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2357                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2358                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2359                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2360                 // ambient model lighting
2361                 mode = SHADERMODE_LIGHTDIRECTION;
2362                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2363                         permutation |= SHADERPERMUTATION_GLOW;
2364                 if (r_refdef.fogenabled)
2365                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2366                 if (rsurface.texture->colormapping)
2367                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2368                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2369                 {
2370                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2371                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2372
2373                         if (r_shadow_shadowmap2ddepthbuffer)
2374                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2375                 }
2376                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2377                         permutation |= SHADERPERMUTATION_REFLECTION;
2378                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2379                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2380                 if (rsurface.texture->reflectmasktexture)
2381                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2382                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2383                 {
2384                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2385                         if (r_shadow_bouncegriddirectional)
2386                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2387                 }
2388                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2389                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2390                 // when using alphatocoverage, we don't need alphakill
2391                 if (vid.allowalphatocoverage)
2392                 {
2393                         if (r_transparent_alphatocoverage.integer)
2394                         {
2395                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2396                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2397                         }
2398                         else
2399                                 GL_AlphaToCoverage(false);
2400                 }
2401         }
2402         else
2403         {
2404                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2405                 {
2406                         switch(rsurface.texture->offsetmapping)
2407                         {
2408                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2409                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2410                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2411                         case OFFSETMAPPING_OFF: break;
2412                         }
2413                 }
2414                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2415                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2416                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2417                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2418                 // lightmapped wall
2419                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2420                         permutation |= SHADERPERMUTATION_GLOW;
2421                 if (r_refdef.fogenabled)
2422                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2423                 if (rsurface.texture->colormapping)
2424                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2425                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2426                 {
2427                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2428                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2429
2430                         if (r_shadow_shadowmap2ddepthbuffer)
2431                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2432                 }
2433                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2434                         permutation |= SHADERPERMUTATION_REFLECTION;
2435                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2436                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2437                 if (rsurface.texture->reflectmasktexture)
2438                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2439                 if (FAKELIGHT_ENABLED)
2440                 {
2441                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2442                         mode = SHADERMODE_FAKELIGHT;
2443                         permutation |= SHADERPERMUTATION_DIFFUSE;
2444                         if (specularscale > 0)
2445                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2446                 }
2447                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2448                 {
2449                         // deluxemapping (light direction texture)
2450                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2451                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2452                         else
2453                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2454                         permutation |= SHADERPERMUTATION_DIFFUSE;
2455                         if (specularscale > 0)
2456                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2457                 }
2458                 else if (r_glsl_deluxemapping.integer >= 2)
2459                 {
2460                         // fake deluxemapping (uniform light direction in tangentspace)
2461                         if (rsurface.uselightmaptexture)
2462                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2463                         else
2464                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2465                         permutation |= SHADERPERMUTATION_DIFFUSE;
2466                         if (specularscale > 0)
2467                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2468                 }
2469                 else if (rsurface.uselightmaptexture)
2470                 {
2471                         // ordinary lightmapping (q1bsp, q3bsp)
2472                         mode = SHADERMODE_LIGHTMAP;
2473                 }
2474                 else
2475                 {
2476                         // ordinary vertex coloring (q3bsp)
2477                         mode = SHADERMODE_VERTEXCOLOR;
2478                 }
2479                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2480                 {
2481                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2482                         if (r_shadow_bouncegriddirectional)
2483                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2484                 }
2485                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2486                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2487                 // when using alphatocoverage, we don't need alphakill
2488                 if (vid.allowalphatocoverage)
2489                 {
2490                         if (r_transparent_alphatocoverage.integer)
2491                         {
2492                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2493                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2494                         }
2495                         else
2496                                 GL_AlphaToCoverage(false);
2497                 }
2498         }
2499         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2500                 colormod = dummy_colormod;
2501         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2502                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2503         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2504                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2505         switch(vid.renderpath)
2506         {
2507         case RENDERPATH_D3D9:
2508 #ifdef SUPPORTD3D
2509                 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);
2510                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2511                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2512                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2513                 if (mode == SHADERMODE_LIGHTSOURCE)
2514                 {
2515                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2516                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2517                 }
2518                 else
2519                 {
2520                         if (mode == SHADERMODE_LIGHTDIRECTION)
2521                         {
2522                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2523                         }
2524                 }
2525                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2526                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2527                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2528                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2529                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2530
2531                 if (mode == SHADERMODE_LIGHTSOURCE)
2532                 {
2533                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2534                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2536                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2537                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2538
2539                         // additive passes are only darkened by fog, not tinted
2540                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2541                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2542                 }
2543                 else
2544                 {
2545                         if (mode == SHADERMODE_FLATCOLOR)
2546                         {
2547                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2548                         }
2549                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2550                         {
2551                                 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]);
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2553                                 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);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2556                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2557                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2558                         }
2559                         else
2560                         {
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2563                                 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);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2565                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2566                         }
2567                         // additive passes are only darkened by fog, not tinted
2568                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2570                         else
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2572                         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);
2573                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2574                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2575                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2576                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2577                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2578                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2579                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2580                         if (mode == SHADERMODE_WATER)
2581                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2582                 }
2583                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2584                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2585                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2586                 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));
2587                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2588                 if (rsurface.texture->pantstexture)
2589                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2590                 else
2591                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2592                 if (rsurface.texture->shirttexture)
2593                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2594                 else
2595                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2596                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2597                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2598                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2599                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2600                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2601                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2602                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2603                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2604                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2605                         );
2606                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2607                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2608                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2609                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2610
2611                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2612                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2613                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2614                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2615                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2616                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2617                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2618                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2619                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2620                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2621                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2622                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2623                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2624                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2625                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2626                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2627                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2628                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2629                 {
2630                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2631                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2632                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2633                 }
2634                 else
2635                 {
2636                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2637                 }
2638 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2639                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2640                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2641                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2642                 {
2643                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2644                         if (rsurface.rtlight)
2645                         {
2646                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2647                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2648                         }
2649                 }
2650 #endif
2651                 break;
2652         case RENDERPATH_D3D10:
2653                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2654                 break;
2655         case RENDERPATH_D3D11:
2656                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2657                 break;
2658         case RENDERPATH_GL20:
2659         case RENDERPATH_GLES2:
2660                 if (!vid.useinterleavedarrays)
2661                 {
2662                         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);
2663                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2664                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2665                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2666                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2667                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2668                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2669                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2670                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2671                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2672                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2673                 }
2674                 else
2675                 {
2676                         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);
2677                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2678                 }
2679                 // this has to be after RSurf_PrepareVerticesForBatch
2680                 if (rsurface.batchskeletaltransform3x4)
2681                         permutation |= SHADERPERMUTATION_SKELETAL;
2682                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2683                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2684                 if (mode == SHADERMODE_LIGHTSOURCE)
2685                 {
2686                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2687                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2688                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2689                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2690                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2691                         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);
2692         
2693                         // additive passes are only darkened by fog, not tinted
2694                         if (r_glsl_permutation->loc_FogColor >= 0)
2695                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2696                         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);
2697                 }
2698                 else
2699                 {
2700                         if (mode == SHADERMODE_FLATCOLOR)
2701                         {
2702                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2703                         }
2704                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2705                         {
2706                                 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]);
2707                                 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]);
2708                                 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);
2709                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2710                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2711                                 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]);
2712                                 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]);
2713                         }
2714                         else
2715                         {
2716                                 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]);
2717                                 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]);
2718                                 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);
2719                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2720                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2721                         }
2722                         // additive passes are only darkened by fog, not tinted
2723                         if (r_glsl_permutation->loc_FogColor >= 0)
2724                         {
2725                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2726                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2727                                 else
2728                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2729                         }
2730                         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);
2731                         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]);
2732                         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]);
2733                         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]);
2734                         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]);
2735                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2736                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2737                         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);
2738                         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]);
2739                 }
2740                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2741                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2742                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2743                 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]);
2744                 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]);
2745
2746                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2747                 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));
2748                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2749                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2750                 {
2751                         if (rsurface.texture->pantstexture)
2752                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2753                         else
2754                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2755                 }
2756                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2757                 {
2758                         if (rsurface.texture->shirttexture)
2759                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2760                         else
2761                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2762                 }
2763                 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]);
2764                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2765                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2766                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2767                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2768                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2769                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2770                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2771                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2772                         );
2773                 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);
2774                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2775                 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]);
2776                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2777                 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);}
2778                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2779
2780                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2781                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2782                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2783                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2784                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2785                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2786                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2787                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2788                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2789                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2790                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2791                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2792                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2793                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2794                 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);
2795                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2796                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2797                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2798                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2799                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2800                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2801                 {
2802                         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);
2803                         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);
2804                         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);
2805                 }
2806                 else
2807                 {
2808                         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);
2809                 }
2810                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2811                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2812                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2813                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2814                 {
2815                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2816                         if (rsurface.rtlight)
2817                         {
2818                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2819                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2820                         }
2821                 }
2822                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2823                 if (r_glsl_permutation->loc_Skeletal_Transform12 >= 0 && rsurface.batchskeletalnumtransforms > 0)
2824                         qglUniform4fv(r_glsl_permutation->loc_Skeletal_Transform12, rsurface.batchskeletalnumtransforms*3, rsurface.batchskeletaltransform3x4);
2825                 CHECKGLERROR
2826                 break;
2827         case RENDERPATH_GL11:
2828         case RENDERPATH_GL13:
2829         case RENDERPATH_GLES1:
2830                 break;
2831         case RENDERPATH_SOFT:
2832                 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);
2833                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2834                 R_SetupShader_SetPermutationSoft(mode, permutation);
2835                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2836                 if (mode == SHADERMODE_LIGHTSOURCE)
2837                 {
2838                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2839                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2840                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2841                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2842                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2843                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2844         
2845                         // additive passes are only darkened by fog, not tinted
2846                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2847                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2848                 }
2849                 else
2850                 {
2851                         if (mode == SHADERMODE_FLATCOLOR)
2852                         {
2853                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2854                         }
2855                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2856                         {
2857                                 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]);
2858                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2859                                 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);
2860                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2861                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2862                                 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]);
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2864                         }
2865                         else
2866                         {
2867                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2868                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2869                                 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);
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2872                         }
2873                         // additive passes are only darkened by fog, not tinted
2874                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2876                         else
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2878                         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);
2879                         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]);
2880                         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]);
2881                         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]);
2882                         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]);
2883                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2884                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2885                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2886                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2887                 }
2888                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2889                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2890                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2891                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2892                 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]);
2893
2894                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2895                 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));
2896                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2897                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2898                 {
2899                         if (rsurface.texture->pantstexture)
2900                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2901                         else
2902                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2903                 }
2904                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2905                 {
2906                         if (rsurface.texture->shirttexture)
2907                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2908                         else
2909                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2910                 }
2911                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2912                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2913                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2914                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2915                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2916                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2917                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2918                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2919                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2920                         );
2921                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2922                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2923                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2924                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2925
2926                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2927                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2928                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2929                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2930                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2931                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2932                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2933                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2934                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2935                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2936                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2937                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2938                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2939                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2940                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2941                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2942                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2943                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2944                 {
2945                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2946                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2947                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2948                 }
2949                 else
2950                 {
2951                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2952                 }
2953 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2954                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2955                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2956                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2957                 {
2958                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2959                         if (rsurface.rtlight)
2960                         {
2961                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2962                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2963                         }
2964                 }
2965                 break;
2966         }
2967 }
2968
2969 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2970 {
2971         // select a permutation of the lighting shader appropriate to this
2972         // combination of texture, entity, light source, and fogging, only use the
2973         // minimum features necessary to avoid wasting rendering time in the
2974         // fragment shader on features that are not being used
2975         unsigned int permutation = 0;
2976         unsigned int mode = 0;
2977         const float *lightcolorbase = rtlight->currentcolor;
2978         float ambientscale = rtlight->ambientscale;
2979         float diffusescale = rtlight->diffusescale;
2980         float specularscale = rtlight->specularscale;
2981         // this is the location of the light in view space
2982         vec3_t viewlightorigin;
2983         // this transforms from view space (camera) to light space (cubemap)
2984         matrix4x4_t viewtolight;
2985         matrix4x4_t lighttoview;
2986         float viewtolight16f[16];
2987         // light source
2988         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2989         if (rtlight->currentcubemap != r_texture_whitecube)
2990                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2991         if (diffusescale > 0)
2992                 permutation |= SHADERPERMUTATION_DIFFUSE;
2993         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2994                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2995         if (r_shadow_usingshadowmap2d)
2996         {
2997                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2998                 if (r_shadow_shadowmapvsdct)
2999                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3000
3001                 if (r_shadow_shadowmap2ddepthbuffer)
3002                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3003         }
3004         if (vid.allowalphatocoverage)
3005                 GL_AlphaToCoverage(false);
3006         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3007         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3008         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3009         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3010         switch(vid.renderpath)
3011         {
3012         case RENDERPATH_D3D9:
3013 #ifdef SUPPORTD3D
3014                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3015                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3016                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3017                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3018                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3019                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3020                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3021                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3022                 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);
3023                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3024                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3025
3026                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3027                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3028                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3029                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3030                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3031 #endif
3032                 break;
3033         case RENDERPATH_D3D10:
3034                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3035                 break;
3036         case RENDERPATH_D3D11:
3037                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3038                 break;
3039         case RENDERPATH_GL20:
3040         case RENDERPATH_GLES2:
3041                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3042                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3043                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3044                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3045                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3046                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3047                 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]);
3048                 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]);
3049                 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);
3050                 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]);
3051                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3052
3053                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3054                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3055                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3056                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3057                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3058                 break;
3059         case RENDERPATH_GL11:
3060         case RENDERPATH_GL13:
3061         case RENDERPATH_GLES1:
3062                 break;
3063         case RENDERPATH_SOFT:
3064                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3065                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3066                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3067                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3068                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3069                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3070                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3071                 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]);
3072                 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);
3073                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3074                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3075
3076                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3077                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3078                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3079                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3080                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3081                 break;
3082         }
3083 }
3084
3085 #define SKINFRAME_HASH 1024
3086
3087 typedef struct
3088 {
3089         int loadsequence; // incremented each level change
3090         memexpandablearray_t array;
3091         skinframe_t *hash[SKINFRAME_HASH];
3092 }
3093 r_skinframe_t;
3094 r_skinframe_t r_skinframe;
3095
3096 void R_SkinFrame_PrepareForPurge(void)
3097 {
3098         r_skinframe.loadsequence++;
3099         // wrap it without hitting zero
3100         if (r_skinframe.loadsequence >= 200)
3101                 r_skinframe.loadsequence = 1;
3102 }
3103
3104 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3105 {
3106         if (!skinframe)
3107                 return;
3108         // mark the skinframe as used for the purging code
3109         skinframe->loadsequence = r_skinframe.loadsequence;
3110 }
3111
3112 void R_SkinFrame_Purge(void)
3113 {
3114         int i;
3115         skinframe_t *s;
3116         for (i = 0;i < SKINFRAME_HASH;i++)
3117         {
3118                 for (s = r_skinframe.hash[i];s;s = s->next)
3119                 {
3120                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3121                         {
3122                                 if (s->merged == s->base)
3123                                         s->merged = NULL;
3124                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3125                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3126                                 R_PurgeTexture(s->merged);s->merged = NULL;
3127                                 R_PurgeTexture(s->base  );s->base   = NULL;
3128                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3129                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3130                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3131                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3132                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3133                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3134                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3135                                 s->loadsequence = 0;
3136                         }
3137                 }
3138         }
3139 }
3140
3141 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3142         skinframe_t *item;
3143         char basename[MAX_QPATH];
3144
3145         Image_StripImageExtension(name, basename, sizeof(basename));
3146
3147         if( last == NULL ) {
3148                 int hashindex;
3149                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3150                 item = r_skinframe.hash[hashindex];
3151         } else {
3152                 item = last->next;
3153         }
3154
3155         // linearly search through the hash bucket
3156         for( ; item ; item = item->next ) {
3157                 if( !strcmp( item->basename, basename ) ) {
3158                         return item;
3159                 }
3160         }
3161         return NULL;
3162 }
3163
3164 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3165 {
3166         skinframe_t *item;
3167         int hashindex;
3168         char basename[MAX_QPATH];
3169
3170         Image_StripImageExtension(name, basename, sizeof(basename));
3171
3172         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3173         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3174                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3175                         break;
3176
3177         if (!item) {
3178                 rtexture_t *dyntexture;
3179                 // check whether its a dynamic texture
3180                 dyntexture = CL_GetDynTexture( basename );
3181                 if (!add && !dyntexture)
3182                         return NULL;
3183                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3184                 memset(item, 0, sizeof(*item));
3185                 strlcpy(item->basename, basename, sizeof(item->basename));
3186                 item->base = dyntexture; // either NULL or dyntexture handle
3187                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3188                 item->comparewidth = comparewidth;
3189                 item->compareheight = compareheight;
3190                 item->comparecrc = comparecrc;
3191                 item->next = r_skinframe.hash[hashindex];
3192                 r_skinframe.hash[hashindex] = item;
3193         }
3194         else if (textureflags & TEXF_FORCE_RELOAD)
3195         {
3196                 rtexture_t *dyntexture;
3197                 // check whether its a dynamic texture
3198                 dyntexture = CL_GetDynTexture( basename );
3199                 if (!add && !dyntexture)
3200                         return NULL;
3201                 if (item->merged == item->base)
3202                         item->merged = NULL;
3203                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3204                 R_PurgeTexture(item->stain );item->stain  = NULL;
3205                 R_PurgeTexture(item->merged);item->merged = NULL;
3206                 R_PurgeTexture(item->base  );item->base   = NULL;
3207                 R_PurgeTexture(item->pants );item->pants  = NULL;
3208                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3209                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3210                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3211                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3212                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3213         R_PurgeTexture(item->reflect);item->reflect = NULL;
3214                 item->loadsequence = 0;
3215         }
3216         else if( item->base == NULL )
3217         {
3218                 rtexture_t *dyntexture;
3219                 // check whether its a dynamic texture
3220                 // 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]
3221                 dyntexture = CL_GetDynTexture( basename );
3222                 item->base = dyntexture; // either NULL or dyntexture handle
3223         }
3224
3225         R_SkinFrame_MarkUsed(item);
3226         return item;
3227 }
3228
3229 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3230         { \
3231                 unsigned long long avgcolor[5], wsum; \
3232                 int pix, comp, w; \
3233                 avgcolor[0] = 0; \
3234                 avgcolor[1] = 0; \
3235                 avgcolor[2] = 0; \
3236                 avgcolor[3] = 0; \
3237                 avgcolor[4] = 0; \
3238                 wsum = 0; \
3239                 for(pix = 0; pix < cnt; ++pix) \
3240                 { \
3241                         w = 0; \
3242                         for(comp = 0; comp < 3; ++comp) \
3243                                 w += getpixel; \
3244                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3245                         { \
3246                                 ++wsum; \
3247                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3248                                 w = getpixel; \
3249                                 for(comp = 0; comp < 3; ++comp) \
3250                                         avgcolor[comp] += getpixel * w; \
3251                                 avgcolor[3] += w; \
3252                         } \
3253                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3254                         avgcolor[4] += getpixel; \
3255                 } \
3256                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3257                         avgcolor[3] = 1; \
3258                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3259                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3260                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3261                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3262         }
3263
3264 extern cvar_t gl_picmip;
3265 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3266 {
3267         int j;
3268         unsigned char *pixels;
3269         unsigned char *bumppixels;
3270         unsigned char *basepixels = NULL;
3271         int basepixels_width = 0;
3272         int basepixels_height = 0;
3273         skinframe_t *skinframe;
3274         rtexture_t *ddsbase = NULL;
3275         qboolean ddshasalpha = false;
3276         float ddsavgcolor[4];
3277         char basename[MAX_QPATH];
3278         int miplevel = R_PicmipForFlags(textureflags);
3279         int savemiplevel = miplevel;
3280         int mymiplevel;
3281         char vabuf[1024];
3282
3283         if (cls.state == ca_dedicated)
3284                 return NULL;
3285
3286         // return an existing skinframe if already loaded
3287         // if loading of the first image fails, don't make a new skinframe as it
3288         // would cause all future lookups of this to be missing
3289         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3290         if (skinframe && skinframe->base)
3291                 return skinframe;
3292
3293         Image_StripImageExtension(name, basename, sizeof(basename));
3294
3295         // check for DDS texture file first
3296         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3297         {
3298                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3299                 if (basepixels == NULL)
3300                         return NULL;
3301         }
3302
3303         // FIXME handle miplevel
3304
3305         if (developer_loading.integer)
3306                 Con_Printf("loading skin \"%s\"\n", name);
3307
3308         // we've got some pixels to store, so really allocate this new texture now
3309         if (!skinframe)
3310                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3311         textureflags &= ~TEXF_FORCE_RELOAD;
3312         skinframe->stain = NULL;
3313         skinframe->merged = NULL;
3314         skinframe->base = NULL;
3315         skinframe->pants = NULL;
3316         skinframe->shirt = NULL;
3317         skinframe->nmap = NULL;
3318         skinframe->gloss = NULL;
3319         skinframe->glow = NULL;
3320         skinframe->fog = NULL;
3321         skinframe->reflect = NULL;
3322         skinframe->hasalpha = false;
3323
3324         if (ddsbase)
3325         {
3326                 skinframe->base = ddsbase;
3327                 skinframe->hasalpha = ddshasalpha;
3328                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3329                 if (r_loadfog && skinframe->hasalpha)
3330                         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);
3331                 //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]);
3332         }
3333         else
3334         {
3335                 basepixels_width = image_width;
3336                 basepixels_height = image_height;
3337                 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);
3338                 if (textureflags & TEXF_ALPHA)
3339                 {
3340                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3341                         {
3342                                 if (basepixels[j] < 255)
3343                                 {
3344                                         skinframe->hasalpha = true;
3345                                         break;
3346                                 }
3347                         }
3348                         if (r_loadfog && skinframe->hasalpha)
3349                         {
3350                                 // has transparent pixels
3351                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3352                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3353                                 {
3354                                         pixels[j+0] = 255;
3355                                         pixels[j+1] = 255;
3356                                         pixels[j+2] = 255;
3357                                         pixels[j+3] = basepixels[j+3];
3358                                 }
3359                                 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);
3360                                 Mem_Free(pixels);
3361                         }
3362                 }
3363                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3364 #ifndef USE_GLES2
3365                 //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]);
3366                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3367                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3368                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3369                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3370 #endif
3371         }
3372
3373         if (r_loaddds)
3374         {
3375                 mymiplevel = savemiplevel;
3376                 if (r_loadnormalmap)
3377                         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);
3378                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3379                 if (r_loadgloss)
3380                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3381                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3382                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3383                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3384         }
3385
3386         // _norm is the name used by tenebrae and has been adopted as standard
3387         if (r_loadnormalmap && skinframe->nmap == NULL)
3388         {
3389                 mymiplevel = savemiplevel;
3390                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3391                 {
3392                         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);
3393                         Mem_Free(pixels);
3394                         pixels = NULL;
3395                 }
3396                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3397                 {
3398                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3399                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
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                         Mem_Free(bumppixels);
3403                 }
3404                 else if (r_shadow_bumpscale_basetexture.value > 0)
3405                 {
3406                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3407                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3408                         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);
3409                         Mem_Free(pixels);
3410                 }
3411 #ifndef USE_GLES2
3412                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3413                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3414 #endif
3415         }
3416
3417         // _luma is supported only for tenebrae compatibility
3418         // _glow is the preferred name
3419         mymiplevel = savemiplevel;
3420         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))))
3421         {
3422                 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);
3423 #ifndef USE_GLES2
3424                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3425                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3426 #endif
3427                 Mem_Free(pixels);pixels = NULL;
3428         }
3429
3430         mymiplevel = savemiplevel;
3431         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3432         {
3433                 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);
3434 #ifndef USE_GLES2
3435                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3436                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3437 #endif
3438                 Mem_Free(pixels);
3439                 pixels = NULL;
3440         }
3441
3442         mymiplevel = savemiplevel;
3443         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3444         {
3445                 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);
3446 #ifndef USE_GLES2
3447                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3448                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3449 #endif
3450                 Mem_Free(pixels);
3451                 pixels = NULL;
3452         }
3453
3454         mymiplevel = savemiplevel;
3455         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3456         {
3457                 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);
3458 #ifndef USE_GLES2
3459                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3460                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3461 #endif
3462                 Mem_Free(pixels);
3463                 pixels = NULL;
3464         }
3465
3466         mymiplevel = savemiplevel;
3467         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3468         {
3469                 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);
3470 #ifndef USE_GLES2
3471                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3472                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3473 #endif
3474                 Mem_Free(pixels);
3475                 pixels = NULL;
3476         }
3477
3478         if (basepixels)
3479                 Mem_Free(basepixels);
3480
3481         return skinframe;
3482 }
3483
3484 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3485 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3486 {
3487         int i;
3488         unsigned char *temp1, *temp2;
3489         skinframe_t *skinframe;
3490         char vabuf[1024];
3491
3492         if (cls.state == ca_dedicated)
3493                 return NULL;
3494
3495         // if already loaded just return it, otherwise make a new skinframe
3496         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3497         if (skinframe->base)
3498                 return skinframe;
3499         textureflags &= ~TEXF_FORCE_RELOAD;
3500
3501         skinframe->stain = NULL;
3502         skinframe->merged = NULL;
3503         skinframe->base = NULL;
3504         skinframe->pants = NULL;
3505         skinframe->shirt = NULL;
3506         skinframe->nmap = NULL;
3507         skinframe->gloss = NULL;
3508         skinframe->glow = NULL;
3509         skinframe->fog = NULL;
3510         skinframe->reflect = NULL;
3511         skinframe->hasalpha = false;
3512
3513         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3514         if (!skindata)
3515                 return NULL;
3516
3517         if (developer_loading.integer)
3518                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3519
3520         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3521         {
3522                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3523                 temp2 = temp1 + width * height * 4;
3524                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3525                 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);
3526                 Mem_Free(temp1);
3527         }
3528         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3529         if (textureflags & TEXF_ALPHA)
3530         {
3531                 for (i = 3;i < width * height * 4;i += 4)
3532                 {
3533                         if (skindata[i] < 255)
3534                         {
3535                                 skinframe->hasalpha = true;
3536                                 break;
3537                         }
3538                 }
3539                 if (r_loadfog && skinframe->hasalpha)
3540                 {
3541                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3542                         memcpy(fogpixels, skindata, width * height * 4);
3543                         for (i = 0;i < width * height * 4;i += 4)
3544                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3545                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3546                         Mem_Free(fogpixels);
3547                 }
3548         }
3549
3550         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3551         //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]);
3552
3553         return skinframe;
3554 }
3555
3556 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3557 {
3558         int i;
3559         int featuresmask;
3560         skinframe_t *skinframe;
3561
3562         if (cls.state == ca_dedicated)
3563                 return NULL;
3564
3565         // if already loaded just return it, otherwise make a new skinframe
3566         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3567         if (skinframe->base)
3568                 return skinframe;
3569         //textureflags &= ~TEXF_FORCE_RELOAD;
3570
3571         skinframe->stain = NULL;
3572         skinframe->merged = NULL;
3573         skinframe->base = NULL;
3574         skinframe->pants = NULL;
3575         skinframe->shirt = NULL;
3576         skinframe->nmap = NULL;
3577         skinframe->gloss = NULL;
3578         skinframe->glow = NULL;
3579         skinframe->fog = NULL;
3580         skinframe->reflect = NULL;
3581         skinframe->hasalpha = false;
3582
3583         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3584         if (!skindata)
3585                 return NULL;
3586
3587         if (developer_loading.integer)
3588                 Con_Printf("loading quake skin \"%s\"\n", name);
3589
3590         // 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)
3591         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3592         memcpy(skinframe->qpixels, skindata, width*height);
3593         skinframe->qwidth = width;
3594         skinframe->qheight = height;
3595
3596         featuresmask = 0;
3597         for (i = 0;i < width * height;i++)
3598                 featuresmask |= palette_featureflags[skindata[i]];
3599
3600         skinframe->hasalpha = false;
3601         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3602         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3603         skinframe->qgeneratemerged = true;
3604         skinframe->qgeneratebase = skinframe->qhascolormapping;
3605         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3606
3607         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3608         //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]);
3609
3610         return skinframe;
3611 }
3612
3613 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3614 {
3615         int width;
3616         int height;
3617         unsigned char *skindata;
3618         char vabuf[1024];
3619
3620         if (!skinframe->qpixels)
3621                 return;
3622
3623         if (!skinframe->qhascolormapping)
3624                 colormapped = false;
3625
3626         if (colormapped)
3627         {
3628                 if (!skinframe->qgeneratebase)
3629                         return;
3630         }
3631         else
3632         {
3633                 if (!skinframe->qgeneratemerged)
3634                         return;
3635         }
3636
3637         width = skinframe->qwidth;
3638         height = skinframe->qheight;
3639         skindata = skinframe->qpixels;
3640
3641         if (skinframe->qgeneratenmap)
3642         {
3643                 unsigned char *temp1, *temp2;
3644                 skinframe->qgeneratenmap = false;
3645                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3646                 temp2 = temp1 + width * height * 4;
3647                 // use either a custom palette or the quake palette
3648                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3649                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3650                 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);
3651                 Mem_Free(temp1);
3652         }
3653
3654         if (skinframe->qgenerateglow)
3655         {
3656                 skinframe->qgenerateglow = false;
3657                 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
3658         }
3659
3660         if (colormapped)
3661         {
3662                 skinframe->qgeneratebase = false;
3663                 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);
3664                 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);
3665                 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);
3666         }
3667         else
3668         {
3669                 skinframe->qgeneratemerged = false;
3670                 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);
3671         }
3672
3673         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3674         {
3675                 Mem_Free(skinframe->qpixels);
3676                 skinframe->qpixels = NULL;
3677         }
3678 }
3679
3680 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)
3681 {
3682         int i;
3683         skinframe_t *skinframe;
3684         char vabuf[1024];
3685
3686         if (cls.state == ca_dedicated)
3687                 return NULL;
3688
3689         // if already loaded just return it, otherwise make a new skinframe
3690         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3691         if (skinframe->base)
3692                 return skinframe;
3693         textureflags &= ~TEXF_FORCE_RELOAD;
3694
3695         skinframe->stain = NULL;
3696         skinframe->merged = NULL;
3697         skinframe->base = NULL;
3698         skinframe->pants = NULL;
3699         skinframe->shirt = NULL;
3700         skinframe->nmap = NULL;
3701         skinframe->gloss = NULL;
3702         skinframe->glow = NULL;
3703         skinframe->fog = NULL;
3704         skinframe->reflect = NULL;
3705         skinframe->hasalpha = false;
3706
3707         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3708         if (!skindata)
3709                 return NULL;
3710
3711         if (developer_loading.integer)
3712                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3713
3714         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3715         if (textureflags & TEXF_ALPHA)
3716         {
3717                 for (i = 0;i < width * height;i++)
3718                 {
3719                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3720                         {
3721                                 skinframe->hasalpha = true;
3722                                 break;
3723                         }
3724                 }
3725                 if (r_loadfog && skinframe->hasalpha)
3726                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3727         }
3728
3729         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3730         //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]);
3731
3732         return skinframe;
3733 }
3734
3735 skinframe_t *R_SkinFrame_LoadMissing(void)
3736 {
3737         skinframe_t *skinframe;
3738
3739         if (cls.state == ca_dedicated)
3740                 return NULL;
3741
3742         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3743         skinframe->stain = NULL;
3744         skinframe->merged = NULL;
3745         skinframe->base = NULL;
3746         skinframe->pants = NULL;
3747         skinframe->shirt = NULL;
3748         skinframe->nmap = NULL;
3749         skinframe->gloss = NULL;
3750         skinframe->glow = NULL;
3751         skinframe->fog = NULL;
3752         skinframe->reflect = NULL;
3753         skinframe->hasalpha = false;
3754
3755         skinframe->avgcolor[0] = rand() / RAND_MAX;
3756         skinframe->avgcolor[1] = rand() / RAND_MAX;
3757         skinframe->avgcolor[2] = rand() / RAND_MAX;
3758         skinframe->avgcolor[3] = 1;
3759
3760         return skinframe;
3761 }
3762
3763 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3764 typedef struct suffixinfo_s
3765 {
3766         const char *suffix;
3767         qboolean flipx, flipy, flipdiagonal;
3768 }
3769 suffixinfo_t;
3770 static suffixinfo_t suffix[3][6] =
3771 {
3772         {
3773                 {"px",   false, false, false},
3774                 {"nx",   false, false, false},
3775                 {"py",   false, false, false},
3776                 {"ny",   false, false, false},
3777                 {"pz",   false, false, false},
3778                 {"nz",   false, false, false}
3779         },
3780         {
3781                 {"posx", false, false, false},
3782                 {"negx", false, false, false},
3783                 {"posy", false, false, false},
3784                 {"negy", false, false, false},
3785                 {"posz", false, false, false},
3786                 {"negz", false, false, false}
3787         },
3788         {
3789                 {"rt",    true, false,  true},
3790                 {"lf",   false,  true,  true},
3791                 {"ft",    true,  true, false},
3792                 {"bk",   false, false, false},
3793                 {"up",    true, false,  true},
3794                 {"dn",    true, false,  true}
3795         }
3796 };
3797
3798 static int componentorder[4] = {0, 1, 2, 3};
3799
3800 static rtexture_t *R_LoadCubemap(const char *basename)
3801 {
3802         int i, j, cubemapsize;
3803         unsigned char *cubemappixels, *image_buffer;
3804         rtexture_t *cubemaptexture;
3805         char name[256];
3806         // must start 0 so the first loadimagepixels has no requested width/height
3807         cubemapsize = 0;
3808         cubemappixels = NULL;
3809         cubemaptexture = NULL;
3810         // keep trying different suffix groups (posx, px, rt) until one loads
3811         for (j = 0;j < 3 && !cubemappixels;j++)
3812         {
3813                 // load the 6 images in the suffix group
3814                 for (i = 0;i < 6;i++)
3815                 {
3816                         // generate an image name based on the base and and suffix
3817                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3818                         // load it
3819                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3820                         {
3821                                 // an image loaded, make sure width and height are equal
3822                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3823                                 {
3824                                         // if this is the first image to load successfully, allocate the cubemap memory
3825                                         if (!cubemappixels && image_width >= 1)
3826                                         {
3827                                                 cubemapsize = image_width;
3828                                                 // note this clears to black, so unavailable sides are black
3829                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3830                                         }
3831                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3832                                         if (cubemappixels)
3833                                                 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);
3834                                 }
3835                                 else
3836                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3837                                 // free the image
3838                                 Mem_Free(image_buffer);
3839                         }
3840                 }
3841         }
3842         // if a cubemap loaded, upload it
3843         if (cubemappixels)
3844         {
3845                 if (developer_loading.integer)
3846                         Con_Printf("loading cubemap \"%s\"\n", basename);
3847
3848                 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);
3849                 Mem_Free(cubemappixels);
3850         }
3851         else
3852         {
3853                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3854                 if (developer_loading.integer)
3855                 {
3856                         Con_Printf("(tried tried images ");
3857                         for (j = 0;j < 3;j++)
3858                                 for (i = 0;i < 6;i++)
3859                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3860                         Con_Print(" and was unable to find any of them).\n");
3861                 }
3862         }
3863         return cubemaptexture;
3864 }
3865
3866 rtexture_t *R_GetCubemap(const char *basename)
3867 {
3868         int i;
3869         for (i = 0;i < r_texture_numcubemaps;i++)
3870                 if (r_texture_cubemaps[i] != NULL)
3871                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3872                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3873         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3874                 return r_texture_whitecube;
3875         r_texture_numcubemaps++;
3876         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3877         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3878         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3879         return r_texture_cubemaps[i]->texture;
3880 }
3881
3882 static void R_Main_FreeViewCache(void)
3883 {
3884         if (r_refdef.viewcache.entityvisible)
3885                 Mem_Free(r_refdef.viewcache.entityvisible);
3886         if (r_refdef.viewcache.world_pvsbits)
3887                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3888         if (r_refdef.viewcache.world_leafvisible)
3889                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3890         if (r_refdef.viewcache.world_surfacevisible)
3891                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3892         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3893 }
3894
3895 static void R_Main_ResizeViewCache(void)
3896 {
3897         int numentities = r_refdef.scene.numentities;
3898         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3899         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3900         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3901         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3902         if (r_refdef.viewcache.maxentities < numentities)
3903         {
3904                 r_refdef.viewcache.maxentities = numentities;
3905                 if (r_refdef.viewcache.entityvisible)
3906                         Mem_Free(r_refdef.viewcache.entityvisible);
3907                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3908         }
3909         if (r_refdef.viewcache.world_numclusters != numclusters)
3910         {
3911                 r_refdef.viewcache.world_numclusters = numclusters;
3912                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3913                 if (r_refdef.viewcache.world_pvsbits)
3914                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3915                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3916         }
3917         if (r_refdef.viewcache.world_numleafs != numleafs)
3918         {
3919                 r_refdef.viewcache.world_numleafs = numleafs;
3920                 if (r_refdef.viewcache.world_leafvisible)
3921                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3922                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3923         }
3924         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3925         {
3926                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3927                 if (r_refdef.viewcache.world_surfacevisible)
3928                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3929                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3930         }
3931 }
3932
3933 extern rtexture_t *loadingscreentexture;
3934 static void gl_main_start(void)
3935 {
3936         loadingscreentexture = NULL;
3937         r_texture_blanknormalmap = NULL;
3938         r_texture_white = NULL;
3939         r_texture_grey128 = NULL;
3940         r_texture_black = NULL;
3941         r_texture_whitecube = NULL;
3942         r_texture_normalizationcube = NULL;
3943         r_texture_fogattenuation = NULL;
3944         r_texture_fogheighttexture = NULL;
3945         r_texture_gammaramps = NULL;
3946         r_texture_numcubemaps = 0;
3947
3948         r_loaddds = r_texture_dds_load.integer != 0;
3949         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3950
3951         switch(vid.renderpath)
3952         {
3953         case RENDERPATH_GL20:
3954         case RENDERPATH_D3D9:
3955         case RENDERPATH_D3D10:
3956         case RENDERPATH_D3D11:
3957         case RENDERPATH_SOFT:
3958         case RENDERPATH_GLES2:
3959                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3960                 Cvar_SetValueQuick(&gl_combine, 1);
3961                 Cvar_SetValueQuick(&r_glsl, 1);
3962                 r_loadnormalmap = true;
3963                 r_loadgloss = true;
3964                 r_loadfog = false;
3965                 break;
3966         case RENDERPATH_GL13:
3967         case RENDERPATH_GLES1:
3968                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3969                 Cvar_SetValueQuick(&gl_combine, 1);
3970                 Cvar_SetValueQuick(&r_glsl, 0);
3971                 r_loadnormalmap = false;
3972                 r_loadgloss = false;
3973                 r_loadfog = true;
3974                 break;
3975         case RENDERPATH_GL11:
3976                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3977                 Cvar_SetValueQuick(&gl_combine, 0);
3978                 Cvar_SetValueQuick(&r_glsl, 0);
3979                 r_loadnormalmap = false;
3980                 r_loadgloss = false;
3981                 r_loadfog = true;
3982                 break;
3983         }
3984
3985         R_AnimCache_Free();
3986         R_FrameData_Reset();
3987
3988         r_numqueries = 0;
3989         r_maxqueries = 0;
3990         memset(r_queries, 0, sizeof(r_queries));
3991
3992         r_qwskincache = NULL;
3993         r_qwskincache_size = 0;
3994
3995         // due to caching of texture_t references, the collision cache must be reset
3996         Collision_Cache_Reset(true);
3997
3998         // set up r_skinframe loading system for textures
3999         memset(&r_skinframe, 0, sizeof(r_skinframe));
4000         r_skinframe.loadsequence = 1;
4001         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4002
4003         r_main_texturepool = R_AllocTexturePool();
4004         R_BuildBlankTextures();
4005         R_BuildNoTexture();
4006         if (vid.support.arb_texture_cube_map)
4007         {
4008                 R_BuildWhiteCube();
4009                 R_BuildNormalizationCube();
4010         }
4011         r_texture_fogattenuation = NULL;
4012         r_texture_fogheighttexture = NULL;
4013         r_texture_gammaramps = NULL;
4014         //r_texture_fogintensity = NULL;
4015         memset(&r_fb, 0, sizeof(r_fb));
4016         r_glsl_permutation = NULL;
4017         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4018         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4019         glslshaderstring = NULL;
4020 #ifdef SUPPORTD3D
4021         r_hlsl_permutation = NULL;
4022         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4023         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4024 #endif
4025         hlslshaderstring = NULL;
4026         memset(&r_svbsp, 0, sizeof (r_svbsp));
4027
4028         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4029         r_texture_numcubemaps = 0;
4030
4031         r_refdef.fogmasktable_density = 0;
4032 }
4033
4034 static void gl_main_shutdown(void)
4035 {
4036         R_AnimCache_Free();
4037         R_FrameData_Reset();
4038
4039         R_Main_FreeViewCache();
4040
4041         switch(vid.renderpath)
4042         {
4043         case RENDERPATH_GL11:
4044         case RENDERPATH_GL13:
4045         case RENDERPATH_GL20:
4046         case RENDERPATH_GLES1:
4047         case RENDERPATH_GLES2:
4048 #ifdef GL_SAMPLES_PASSED_ARB
4049                 if (r_maxqueries)
4050                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4051 #endif
4052                 break;
4053         case RENDERPATH_D3D9:
4054                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4055                 break;
4056         case RENDERPATH_D3D10:
4057                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4058                 break;
4059         case RENDERPATH_D3D11:
4060                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4061                 break;
4062         case RENDERPATH_SOFT:
4063                 break;
4064         }
4065
4066         r_numqueries = 0;
4067         r_maxqueries = 0;
4068         memset(r_queries, 0, sizeof(r_queries));
4069
4070         r_qwskincache = NULL;
4071         r_qwskincache_size = 0;
4072
4073         // clear out the r_skinframe state
4074         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4075         memset(&r_skinframe, 0, sizeof(r_skinframe));
4076
4077         if (r_svbsp.nodes)
4078                 Mem_Free(r_svbsp.nodes);
4079         memset(&r_svbsp, 0, sizeof (r_svbsp));
4080         R_FreeTexturePool(&r_main_texturepool);
4081         loadingscreentexture = NULL;
4082         r_texture_blanknormalmap = NULL;
4083         r_texture_white = NULL;
4084         r_texture_grey128 = NULL;
4085         r_texture_black = NULL;
4086         r_texture_whitecube = NULL;
4087         r_texture_normalizationcube = NULL;
4088         r_texture_fogattenuation = NULL;
4089         r_texture_fogheighttexture = NULL;
4090         r_texture_gammaramps = NULL;
4091         r_texture_numcubemaps = 0;
4092         //r_texture_fogintensity = NULL;
4093         memset(&r_fb, 0, sizeof(r_fb));
4094         R_GLSL_Restart_f();
4095
4096         r_glsl_permutation = NULL;
4097         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4098         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4099         glslshaderstring = NULL;
4100 #ifdef SUPPORTD3D
4101         r_hlsl_permutation = NULL;
4102         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4103         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4104 #endif
4105         hlslshaderstring = NULL;
4106 }
4107
4108 static void gl_main_newmap(void)
4109 {
4110         // FIXME: move this code to client
4111         char *entities, entname[MAX_QPATH];
4112         if (r_qwskincache)
4113                 Mem_Free(r_qwskincache);
4114         r_qwskincache = NULL;
4115         r_qwskincache_size = 0;
4116         if (cl.worldmodel)
4117         {
4118                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4119                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4120                 {
4121                         CL_ParseEntityLump(entities);
4122                         Mem_Free(entities);
4123                         return;
4124                 }
4125                 if (cl.worldmodel->brush.entities)
4126                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4127         }
4128         R_Main_FreeViewCache();
4129
4130         R_FrameData_Reset();
4131 }
4132
4133 void GL_Main_Init(void)
4134 {
4135         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4136
4137         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4138         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4139         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4140         if (gamemode == GAME_NEHAHRA)
4141         {
4142                 Cvar_RegisterVariable (&gl_fogenable);
4143                 Cvar_RegisterVariable (&gl_fogdensity);
4144                 Cvar_RegisterVariable (&gl_fogred);
4145                 Cvar_RegisterVariable (&gl_foggreen);
4146                 Cvar_RegisterVariable (&gl_fogblue);
4147                 Cvar_RegisterVariable (&gl_fogstart);
4148                 Cvar_RegisterVariable (&gl_fogend);
4149                 Cvar_RegisterVariable (&gl_skyclip);
4150         }
4151         Cvar_RegisterVariable(&r_motionblur);
4152         Cvar_RegisterVariable(&r_damageblur);
4153         Cvar_RegisterVariable(&r_motionblur_averaging);
4154         Cvar_RegisterVariable(&r_motionblur_randomize);
4155         Cvar_RegisterVariable(&r_motionblur_minblur);
4156         Cvar_RegisterVariable(&r_motionblur_maxblur);
4157         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4158         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4159         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4160         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4161         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4162         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4163         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4164         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4165         Cvar_RegisterVariable(&r_equalize_entities_by);
4166         Cvar_RegisterVariable(&r_equalize_entities_to);
4167         Cvar_RegisterVariable(&r_depthfirst);
4168         Cvar_RegisterVariable(&r_useinfinitefarclip);
4169         Cvar_RegisterVariable(&r_farclip_base);
4170         Cvar_RegisterVariable(&r_farclip_world);
4171         Cvar_RegisterVariable(&r_nearclip);
4172         Cvar_RegisterVariable(&r_deformvertexes);
4173         Cvar_RegisterVariable(&r_transparent);
4174         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4175         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4176         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4177         Cvar_RegisterVariable(&r_showoverdraw);
4178         Cvar_RegisterVariable(&r_showbboxes);
4179         Cvar_RegisterVariable(&r_showsurfaces);
4180         Cvar_RegisterVariable(&r_showtris);
4181         Cvar_RegisterVariable(&r_shownormals);
4182         Cvar_RegisterVariable(&r_showlighting);
4183         Cvar_RegisterVariable(&r_showshadowvolumes);
4184         Cvar_RegisterVariable(&r_showcollisionbrushes);
4185         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4186         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4187         Cvar_RegisterVariable(&r_showdisabledepthtest);
4188         Cvar_RegisterVariable(&r_drawportals);
4189         Cvar_RegisterVariable(&r_drawentities);
4190         Cvar_RegisterVariable(&r_draw2d);
4191         Cvar_RegisterVariable(&r_drawworld);
4192         Cvar_RegisterVariable(&r_cullentities_trace);
4193         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4194         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4195         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4196         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4197         Cvar_RegisterVariable(&r_sortentities);
4198         Cvar_RegisterVariable(&r_drawviewmodel);
4199         Cvar_RegisterVariable(&r_drawexteriormodel);
4200         Cvar_RegisterVariable(&r_speeds);
4201         Cvar_RegisterVariable(&r_fullbrights);
4202         Cvar_RegisterVariable(&r_wateralpha);
4203         Cvar_RegisterVariable(&r_dynamic);
4204         Cvar_RegisterVariable(&r_fakelight);
4205         Cvar_RegisterVariable(&r_fakelight_intensity);
4206         Cvar_RegisterVariable(&r_fullbright);
4207         Cvar_RegisterVariable(&r_shadows);
4208         Cvar_RegisterVariable(&r_shadows_darken);
4209         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4210         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4211         Cvar_RegisterVariable(&r_shadows_throwdistance);
4212         Cvar_RegisterVariable(&r_shadows_throwdirection);
4213         Cvar_RegisterVariable(&r_shadows_focus);
4214         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4215         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4216         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4217         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4218         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4219         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4220         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4221         Cvar_RegisterVariable(&r_fog_exp2);
4222         Cvar_RegisterVariable(&r_fog_clear);
4223         Cvar_RegisterVariable(&r_drawfog);
4224         Cvar_RegisterVariable(&r_transparentdepthmasking);
4225         Cvar_RegisterVariable(&r_transparent_sortmindist);
4226         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4227         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4228         Cvar_RegisterVariable(&r_texture_dds_load);
4229         Cvar_RegisterVariable(&r_texture_dds_save);
4230         Cvar_RegisterVariable(&r_textureunits);
4231         Cvar_RegisterVariable(&gl_combine);
4232         Cvar_RegisterVariable(&r_usedepthtextures);
4233         Cvar_RegisterVariable(&r_viewfbo);
4234         Cvar_RegisterVariable(&r_viewscale);
4235         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4236         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4237         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4238         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4239         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4240         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4241         Cvar_RegisterVariable(&r_glsl);
4242         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4243         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4244         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4245         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4246         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4247         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4248         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4249         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4250         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4251         Cvar_RegisterVariable(&r_glsl_postprocess);
4252         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4253         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4254         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4255         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4256         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4257         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4258         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4259         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4260         Cvar_RegisterVariable(&r_celshading);
4261         Cvar_RegisterVariable(&r_celoutlines);
4262
4263         Cvar_RegisterVariable(&r_water);
4264         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4265         Cvar_RegisterVariable(&r_water_clippingplanebias);
4266         Cvar_RegisterVariable(&r_water_refractdistort);
4267         Cvar_RegisterVariable(&r_water_reflectdistort);
4268         Cvar_RegisterVariable(&r_water_scissormode);
4269         Cvar_RegisterVariable(&r_water_lowquality);
4270         Cvar_RegisterVariable(&r_water_hideplayer);
4271         Cvar_RegisterVariable(&r_water_fbo);
4272
4273         Cvar_RegisterVariable(&r_lerpsprites);
4274         Cvar_RegisterVariable(&r_lerpmodels);
4275         Cvar_RegisterVariable(&r_lerplightstyles);
4276         Cvar_RegisterVariable(&r_waterscroll);
4277         Cvar_RegisterVariable(&r_bloom);
4278         Cvar_RegisterVariable(&r_bloom_colorscale);
4279         Cvar_RegisterVariable(&r_bloom_brighten);
4280         Cvar_RegisterVariable(&r_bloom_blur);
4281         Cvar_RegisterVariable(&r_bloom_resolution);
4282         Cvar_RegisterVariable(&r_bloom_colorexponent);
4283         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4284         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4285         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4286         Cvar_RegisterVariable(&r_hdr_glowintensity);
4287         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4288         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4289         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4290         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4291         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4292         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4293         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4294         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4295         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4296         Cvar_RegisterVariable(&developer_texturelogging);
4297         Cvar_RegisterVariable(&gl_lightmaps);
4298         Cvar_RegisterVariable(&r_test);
4299         Cvar_RegisterVariable(&r_batch_multidraw);
4300         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4301         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4302         Cvar_RegisterVariable(&r_glsl_skeletal);
4303         Cvar_RegisterVariable(&r_glsl_saturation);
4304         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4305         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4306         Cvar_RegisterVariable(&r_framedatasize);
4307         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4308                 Cvar_SetValue("r_fullbrights", 0);
4309         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4310 }
4311
4312 void Render_Init(void)
4313 {
4314         gl_backend_init();
4315         R_Textures_Init();
4316         GL_Main_Init();
4317         Font_Init();
4318         GL_Draw_Init();
4319         R_Shadow_Init();
4320         R_Sky_Init();
4321         GL_Surf_Init();
4322         Sbar_Init();
4323         R_Particles_Init();
4324         R_Explosion_Init();
4325         R_LightningBeams_Init();
4326         Mod_RenderInit();
4327 }
4328
4329 /*
4330 ===============
4331 GL_Init
4332 ===============
4333 */
4334 #ifndef USE_GLES2
4335 extern char *ENGINE_EXTENSIONS;
4336 void GL_Init (void)
4337 {
4338         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4339         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4340         gl_version = (const char *)qglGetString(GL_VERSION);
4341         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4342
4343         if (!gl_extensions)
4344                 gl_extensions = "";
4345         if (!gl_platformextensions)
4346                 gl_platformextensions = "";
4347
4348         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4349         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4350         Con_Printf("GL_VERSION: %s\n", gl_version);
4351         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4352         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4353
4354         VID_CheckExtensions();
4355
4356         // LordHavoc: report supported extensions
4357         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4358
4359         // clear to black (loading plaque will be seen over this)
4360         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4361 }
4362 #endif
4363
4364 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4365 {
4366         int i;
4367         mplane_t *p;
4368         if (r_trippy.integer)
4369                 return false;
4370         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4371         {
4372                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4373                 if (i == 4)
4374                         continue;
4375                 p = r_refdef.view.frustum + i;
4376                 switch(p->signbits)
4377                 {
4378                 default:
4379                 case 0:
4380                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4381                                 return true;
4382                         break;
4383                 case 1:
4384                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4385                                 return true;
4386                         break;
4387                 case 2:
4388                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4389                                 return true;
4390                         break;
4391                 case 3:
4392                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4393                                 return true;
4394                         break;
4395                 case 4:
4396                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4397                                 return true;
4398                         break;
4399                 case 5:
4400                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4401                                 return true;
4402                         break;
4403                 case 6:
4404                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4405                                 return true;
4406                         break;
4407                 case 7:
4408                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4409                                 return true;
4410                         break;
4411                 }
4412         }
4413         return false;
4414 }
4415
4416 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4417 {
4418         int i;
4419         const mplane_t *p;
4420         if (r_trippy.integer)
4421                 return false;
4422         for (i = 0;i < numplanes;i++)
4423         {
4424                 p = planes + i;
4425                 switch(p->signbits)
4426                 {
4427                 default:
4428                 case 0:
4429                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4430                                 return true;
4431                         break;
4432                 case 1:
4433                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4434                                 return true;
4435                         break;
4436                 case 2:
4437                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4438                                 return true;
4439                         break;
4440                 case 3:
4441                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4442                                 return true;
4443                         break;
4444                 case 4:
4445                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4446                                 return true;
4447                         break;
4448                 case 5:
4449                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4450                                 return true;
4451                         break;
4452                 case 6:
4453                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4454                                 return true;
4455                         break;
4456                 case 7:
4457                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4458                                 return true;
4459                         break;
4460                 }
4461         }
4462         return false;
4463 }
4464
4465 //==================================================================================
4466
4467 // LordHavoc: this stores temporary data used within the same frame
4468
4469 typedef struct r_framedata_mem_s
4470 {
4471         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4472         size_t size; // how much usable space
4473         size_t current; // how much space in use
4474         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4475         size_t wantedsize; // how much space was allocated
4476         unsigned char *data; // start of real data (16byte aligned)
4477 }
4478 r_framedata_mem_t;
4479
4480 static r_framedata_mem_t *r_framedata_mem;
4481
4482 void R_FrameData_Reset(void)
4483 {
4484         while (r_framedata_mem)
4485         {
4486                 r_framedata_mem_t *next = r_framedata_mem->purge;
4487                 Mem_Free(r_framedata_mem);
4488                 r_framedata_mem = next;
4489         }
4490 }
4491
4492 static void R_FrameData_Resize(void)
4493 {
4494         size_t wantedsize;
4495         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4496         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4497         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4498         {
4499                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4500                 newmem->wantedsize = wantedsize;
4501                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4502                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4503                 newmem->current = 0;
4504                 newmem->mark = 0;
4505                 newmem->purge = r_framedata_mem;
4506                 r_framedata_mem = newmem;
4507         }
4508 }
4509
4510 void R_FrameData_NewFrame(void)
4511 {
4512         R_FrameData_Resize();
4513         if (!r_framedata_mem)
4514                 return;
4515         // if we ran out of space on the last frame, free the old memory now
4516         while (r_framedata_mem->purge)
4517         {
4518                 // repeatedly remove the second item in the list, leaving only head
4519                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4520                 Mem_Free(r_framedata_mem->purge);
4521                 r_framedata_mem->purge = next;
4522         }
4523         // reset the current mem pointer
4524         r_framedata_mem->current = 0;
4525         r_framedata_mem->mark = 0;
4526 }
4527
4528 void *R_FrameData_Alloc(size_t size)
4529 {
4530         void *data;
4531
4532         // align to 16 byte boundary - the data pointer is already aligned, so we
4533         // only need to ensure the size of every allocation is also aligned
4534         size = (size + 15) & ~15;
4535
4536         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4537         {
4538                 // emergency - we ran out of space, allocate more memory
4539                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4540                 R_FrameData_Resize();
4541         }
4542
4543         data = r_framedata_mem->data + r_framedata_mem->current;
4544         r_framedata_mem->current += size;
4545
4546         // count the usage for stats
4547         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4548         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4549
4550         return (void *)data;
4551 }
4552
4553 void *R_FrameData_Store(size_t size, void *data)
4554 {
4555         void *d = R_FrameData_Alloc(size);
4556         if (d && data)
4557                 memcpy(d, data, size);
4558         return d;
4559 }
4560
4561 void R_FrameData_SetMark(void)
4562 {
4563         if (!r_framedata_mem)
4564                 return;
4565         r_framedata_mem->mark = r_framedata_mem->current;
4566 }
4567
4568 void R_FrameData_ReturnToMark(void)
4569 {
4570         if (!r_framedata_mem)
4571                 return;
4572         r_framedata_mem->current = r_framedata_mem->mark;
4573 }
4574
4575 //==================================================================================
4576
4577 // LordHavoc: animcache originally written by Echon, rewritten since then
4578
4579 /**
4580  * Animation cache prevents re-generating mesh data for an animated model
4581  * multiple times in one frame for lighting, shadowing, reflections, etc.
4582  */
4583
4584 void R_AnimCache_Free(void)
4585 {
4586 }
4587
4588 void R_AnimCache_ClearCache(void)
4589 {
4590         int i;
4591         entity_render_t *ent;
4592
4593         for (i = 0;i < r_refdef.scene.numentities;i++)
4594         {
4595                 ent = r_refdef.scene.entities[i];
4596                 ent->animcache_vertex3f = NULL;
4597                 ent->animcache_normal3f = NULL;
4598                 ent->animcache_svector3f = NULL;
4599                 ent->animcache_tvector3f = NULL;
4600                 ent->animcache_vertexmesh = NULL;
4601                 ent->animcache_vertex3fbuffer = NULL;
4602                 ent->animcache_vertexmeshbuffer = NULL;
4603                 ent->animcache_skeletaltransform3x4 = NULL;
4604         }
4605 }
4606
4607 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4608 {
4609         int i;
4610
4611         // check if we need the meshbuffers
4612         if (!vid.useinterleavedarrays)
4613                 return;
4614
4615         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4616                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4617         // TODO: upload vertex3f buffer?
4618         if (ent->animcache_vertexmesh)
4619         {
4620                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4621                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4622                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4623                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4624                 for (i = 0;i < numvertices;i++)
4625                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4626                 if (ent->animcache_svector3f)
4627                         for (i = 0;i < numvertices;i++)
4628                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4629                 if (ent->animcache_tvector3f)
4630                         for (i = 0;i < numvertices;i++)
4631                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4632                 if (ent->animcache_normal3f)
4633                         for (i = 0;i < numvertices;i++)
4634                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4635                 // TODO: upload vertexmeshbuffer?
4636         }
4637 }
4638
4639 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4640 {
4641         dp_model_t *model = ent->model;
4642         int numvertices;
4643
4644         // see if this ent is worth caching
4645         if (!model || !model->Draw || !model->AnimateVertices)
4646                 return false;
4647         // nothing to cache if it contains no animations and has no skeleton
4648         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4649                 return false;
4650         // see if it is already cached for gpuskeletal
4651         if (ent->animcache_skeletaltransform3x4)
4652                 return false;
4653         // see if it is already cached as a mesh
4654         if (ent->animcache_vertex3f)
4655         {
4656                 // check if we need to add normals or tangents
4657                 if (ent->animcache_normal3f)
4658                         wantnormals = false;
4659                 if (ent->animcache_svector3f)
4660                         wanttangents = false;
4661                 if (!wantnormals && !wanttangents)
4662                         return false;
4663         }
4664
4665         // check which kind of cache we need to generate
4666         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4667         {
4668                 // cache the skeleton so the vertex shader can use it
4669                 int i;
4670                 int blends;
4671                 const skeleton_t *skeleton = ent->skeleton;
4672                 const frameblend_t *frameblend = ent->frameblend;
4673                 float *boneposerelative;
4674                 float m[12];
4675                 static float bonepose[256][12];
4676                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4677                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4678                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4679                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4680                 boneposerelative = ent->animcache_skeletaltransform3x4;
4681                 if (skeleton && !skeleton->relativetransforms)
4682                         skeleton = NULL;
4683                 // resolve hierarchy and make relative transforms (deforms) which the shader wants
4684                 if (skeleton)
4685                 {
4686                         for (i = 0;i < model->num_bones;i++)
4687                         {
4688                                 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
4689                                 if (model->data_bones[i].parent >= 0)
4690                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4691                                 else
4692                                         memcpy(bonepose[i], m, sizeof(m));
4693
4694                                 // create a relative deformation matrix to describe displacement
4695                                 // from the base mesh, which is used by the actual weighting
4696                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4697                         }
4698                 }
4699                 else
4700                 {
4701                         for (i = 0;i < model->num_bones;i++)
4702                         {
4703                                 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
4704                                 float lerp = frameblend[0].lerp,
4705                                         tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4706                                         rx = pose7s[3] * lerp,
4707                                         ry = pose7s[4] * lerp,
4708                                         rz = pose7s[5] * lerp,
4709                                         rw = pose7s[6] * lerp,
4710                                         dx = tx*rw + ty*rz - tz*ry,
4711                                         dy = -tx*rz + ty*rw + tz*rx,
4712                                         dz = tx*ry - ty*rx + tz*rw,
4713                                         dw = -tx*rx - ty*ry - tz*rz,
4714                                         scale, sx, sy, sz, sw;
4715                                 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
4716                                 {
4717                                         const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
4718                                         float lerp = frameblend[blends].lerp,
4719                                                 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4720                                                 qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
4721                                         if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
4722                                         qx *= lerp;
4723                                         qy *= lerp;
4724                                         qz *= lerp;
4725                                         qw *= lerp;
4726                                         rx += qx;
4727                                         ry += qy;
4728                                         rz += qz;
4729                                         rw += qw;
4730                                         dx += tx*qw + ty*qz - tz*qy;
4731                                         dy += -tx*qz + ty*qw + tz*qx;
4732                                         dz += tx*qy - ty*qx + tz*qw;
4733                                         dw += -tx*qx - ty*qy - tz*qz;
4734                                 }
4735                                 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
4736                                 sx = rx * scale;
4737                                 sy = ry * scale;
4738                                 sz = rz * scale;
4739                                 sw = rw * scale;
4740                                 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
4741                                 m[1] = 2*(sx*ry - sw*rz);
4742                                 m[2] = 2*(sx*rz + sw*ry);
4743                                 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
4744                                 m[4] = 2*(sx*ry + sw*rz);
4745                                 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
4746                                 m[6] = 2*(sy*rz - sw*rx);
4747                                 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
4748                                 m[8] = 2*(sx*rz - sw*ry);
4749                                 m[9] = 2*(sy*rz + sw*rx);
4750                                 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
4751                                 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
4752                                 if (i == r_skeletal_debugbone.integer)
4753                                         m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
4754                                 m[3] *= r_skeletal_debugtranslatex.value;
4755                                 m[7] *= r_skeletal_debugtranslatey.value;
4756                                 m[11] *= r_skeletal_debugtranslatez.value;
4757                                 if (model->data_bones[i].parent >= 0)
4758                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4759                                 else
4760                                         memcpy(bonepose[i], m, sizeof(m));
4761                                 // create a relative deformation matrix to describe displacement
4762                                 // from the base mesh, which is used by the actual weighting
4763                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4764                         }
4765                 }
4766         }
4767         else if (ent->animcache_vertex3f)
4768         {
4769                 // mesh was already cached but we may need to add normals/tangents
4770                 // (this only happens with multiple views, reflections, cameras, etc)
4771                 if (wantnormals || wanttangents)
4772                 {
4773                         numvertices = model->surfmesh.num_vertices;
4774                         if (wantnormals)
4775                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4776                         if (wanttangents)
4777                         {
4778                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4779                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4780                         }
4781                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4782                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4783                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4784                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4785                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4786                 }
4787         }
4788         else
4789         {
4790                 // generate mesh cache
4791                 numvertices = model->surfmesh.num_vertices;
4792                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4793                 if (wantnormals)
4794                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4795                 if (wanttangents)
4796                 {
4797                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4798                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4799                 }
4800                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4801                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4802                 if (wantnormals || wanttangents)
4803                 {
4804                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4805                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4806                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4807                 }
4808                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4809                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4810                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4811         }
4812         return true;
4813 }
4814
4815 void R_AnimCache_CacheVisibleEntities(void)
4816 {
4817         int i;
4818         qboolean wantnormals = true;
4819         qboolean wanttangents = !r_showsurfaces.integer;
4820
4821         switch(vid.renderpath)
4822         {
4823         case RENDERPATH_GL20:
4824         case RENDERPATH_D3D9:
4825         case RENDERPATH_D3D10:
4826         case RENDERPATH_D3D11:
4827         case RENDERPATH_GLES2:
4828                 break;
4829         case RENDERPATH_GL11:
4830         case RENDERPATH_GL13:
4831         case RENDERPATH_GLES1:
4832                 wanttangents = false;
4833                 break;
4834         case RENDERPATH_SOFT:
4835                 break;
4836         }
4837
4838         if (r_shownormals.integer)
4839                 wanttangents = wantnormals = true;
4840
4841         // TODO: thread this
4842         // NOTE: R_PrepareRTLights() also caches entities
4843
4844         for (i = 0;i < r_refdef.scene.numentities;i++)
4845                 if (r_refdef.viewcache.entityvisible[i])
4846                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4847 }
4848
4849 //==================================================================================
4850
4851 extern cvar_t r_overheadsprites_pushback;
4852
4853 static void R_View_UpdateEntityLighting (void)
4854 {
4855         int i;
4856         entity_render_t *ent;
4857         vec3_t tempdiffusenormal, avg;
4858         vec_t f, fa, fd, fdd;
4859         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4860
4861         for (i = 0;i < r_refdef.scene.numentities;i++)
4862         {
4863                 ent = r_refdef.scene.entities[i];
4864
4865                 // skip unseen models
4866                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4867                         continue;
4868
4869                 // skip bsp models
4870                 if (ent->model && ent->model == cl.worldmodel)
4871                 {
4872                         // TODO: use modellight for r_ambient settings on world?
4873                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4874                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4875                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4876                         continue;
4877                 }
4878                 
4879                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4880                 {
4881                         // aleady updated by CSQC
4882                         // TODO: force modellight on BSP models in this case?
4883                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4884                 }
4885                 else
4886                 {
4887                         // fetch the lighting from the worldmodel data
4888                         VectorClear(ent->modellight_ambient);
4889                         VectorClear(ent->modellight_diffuse);
4890                         VectorClear(tempdiffusenormal);
4891                         if (ent->flags & RENDER_LIGHT)
4892                         {
4893                                 vec3_t org;
4894                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4895
4896                                 // complete lightning for lit sprites
4897                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4898                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4899                                 {
4900                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4901                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4902                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4903                                 }
4904                                 else
4905                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4906
4907                                 if(ent->flags & RENDER_EQUALIZE)
4908                                 {
4909                                         // first fix up ambient lighting...
4910                                         if(r_equalize_entities_minambient.value > 0)
4911                                         {
4912                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4913                                                 if(fd > 0)
4914                                                 {
4915                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4916                                                         if(fa < r_equalize_entities_minambient.value * fd)
4917                                                         {
4918                                                                 // solve:
4919                                                                 //   fa'/fd' = minambient
4920                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4921                                                                 //   ...
4922                                                                 //   fa' = fd' * minambient
4923                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4924                                                                 //   ...
4925                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4926                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4927                                                                 //   ...
4928                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4929                                                                 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
4930                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4931                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4932                                                         }
4933                                                 }
4934                                         }
4935
4936                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4937                                         {
4938                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4939                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4940                                                 f = fa + 0.25 * fd;
4941                                                 if(f > 0)
4942                                                 {
4943                                                         // adjust brightness and saturation to target
4944                                                         avg[0] = avg[1] = avg[2] = fa / f;
4945                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4946                                                         avg[0] = avg[1] = avg[2] = fd / f;
4947                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4948                                                 }
4949                                         }
4950                                 }
4951                         }
4952                         else // highly rare
4953                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4954                 }
4955
4956                 // move the light direction into modelspace coordinates for lighting code
4957                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4958                 if(VectorLength2(ent->modellight_lightdir) == 0)
4959                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4960                 VectorNormalize(ent->modellight_lightdir);
4961         }
4962 }
4963
4964 #define MAX_LINEOFSIGHTTRACES 64
4965
4966 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4967 {
4968         int i;
4969         vec3_t boxmins, boxmaxs;
4970         vec3_t start;
4971         vec3_t end;
4972         dp_model_t *model = r_refdef.scene.worldmodel;
4973
4974         if (!model || !model->brush.TraceLineOfSight)
4975                 return true;
4976
4977         // expand the box a little
4978         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4979         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4980         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4981         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4982         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4983         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4984
4985         // return true if eye is inside enlarged box
4986         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4987                 return true;
4988
4989         // try center
4990         VectorCopy(eye, start);
4991         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4992         if (model->brush.TraceLineOfSight(model, start, end))
4993                 return true;
4994
4995         // try various random positions
4996         for (i = 0;i < numsamples;i++)
4997         {
4998                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4999                 if (model->brush.TraceLineOfSight(model, start, end))
5000                         return true;
5001         }
5002
5003         return false;
5004 }
5005
5006
5007 static void R_View_UpdateEntityVisible (void)
5008 {
5009         int i;
5010         int renderimask;
5011         int samples;
5012         entity_render_t *ent;
5013
5014         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5015                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5016                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5017                 :                                                          RENDER_EXTERIORMODEL;
5018         if (!r_drawviewmodel.integer)
5019                 renderimask |= RENDER_VIEWMODEL;
5020         if (!r_drawexteriormodel.integer)
5021                 renderimask |= RENDER_EXTERIORMODEL;
5022         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5023         {
5024                 // worldmodel can check visibility
5025                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5026                 for (i = 0;i < r_refdef.scene.numentities;i++)
5027                 {
5028                         ent = r_refdef.scene.entities[i];
5029                         if (!(ent->flags & renderimask))
5030                         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)))
5031                         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))
5032                                 r_refdef.viewcache.entityvisible[i] = true;
5033                 }
5034         }
5035         else
5036         {
5037                 // no worldmodel or it can't check visibility
5038                 for (i = 0;i < r_refdef.scene.numentities;i++)
5039                 {
5040                         ent = r_refdef.scene.entities[i];
5041                         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));
5042                 }
5043         }
5044         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5045                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5046         {
5047                 for (i = 0;i < r_refdef.scene.numentities;i++)
5048                 {
5049                         if (!r_refdef.viewcache.entityvisible[i])
5050                                 continue;
5051                         ent = r_refdef.scene.entities[i];
5052                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5053                         {
5054                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5055                                 if (samples < 0)
5056                                         continue; // temp entities do pvs only
5057                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5058                                         ent->last_trace_visibility = realtime;
5059                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5060                                         r_refdef.viewcache.entityvisible[i] = 0;
5061                         }
5062                 }
5063         }
5064 }
5065
5066 /// only used if skyrendermasked, and normally returns false
5067 static int R_DrawBrushModelsSky (void)
5068 {
5069         int i, sky;
5070         entity_render_t *ent;
5071
5072         sky = false;
5073         for (i = 0;i < r_refdef.scene.numentities;i++)
5074         {
5075                 if (!r_refdef.viewcache.entityvisible[i])
5076                         continue;
5077                 ent = r_refdef.scene.entities[i];
5078                 if (!ent->model || !ent->model->DrawSky)
5079                         continue;
5080                 ent->model->DrawSky(ent);
5081                 sky = true;
5082         }
5083         return sky;
5084 }
5085
5086 static void R_DrawNoModel(entity_render_t *ent);
5087 static void R_DrawModels(void)
5088 {
5089         int i;
5090         entity_render_t *ent;
5091
5092         for (i = 0;i < r_refdef.scene.numentities;i++)
5093         {
5094                 if (!r_refdef.viewcache.entityvisible[i])
5095                         continue;
5096                 ent = r_refdef.scene.entities[i];
5097                 r_refdef.stats[r_stat_entities]++;
5098                 /*
5099                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5100                 {
5101                         vec3_t f, l, u, o;
5102                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5103                         Con_Printf("R_DrawModels\n");
5104                         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]);
5105                         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);
5106                         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);
5107                 }
5108                 */
5109                 if (ent->model && ent->model->Draw != NULL)
5110                         ent->model->Draw(ent);
5111                 else
5112                         R_DrawNoModel(ent);
5113         }
5114 }
5115
5116 static void R_DrawModelsDepth(void)
5117 {
5118         int i;
5119         entity_render_t *ent;
5120
5121         for (i = 0;i < r_refdef.scene.numentities;i++)
5122         {
5123                 if (!r_refdef.viewcache.entityvisible[i])
5124                         continue;
5125                 ent = r_refdef.scene.entities[i];
5126                 if (ent->model && ent->model->DrawDepth != NULL)
5127                         ent->model->DrawDepth(ent);
5128         }
5129 }
5130
5131 static void R_DrawModelsDebug(void)
5132 {
5133         int i;
5134         entity_render_t *ent;
5135
5136         for (i = 0;i < r_refdef.scene.numentities;i++)
5137         {
5138                 if (!r_refdef.viewcache.entityvisible[i])
5139                         continue;
5140                 ent = r_refdef.scene.entities[i];
5141                 if (ent->model && ent->model->DrawDebug != NULL)
5142                         ent->model->DrawDebug(ent);
5143         }
5144 }
5145
5146 static void R_DrawModelsAddWaterPlanes(void)
5147 {
5148         int i;
5149         entity_render_t *ent;
5150
5151         for (i = 0;i < r_refdef.scene.numentities;i++)
5152         {
5153                 if (!r_refdef.viewcache.entityvisible[i])
5154                         continue;
5155                 ent = r_refdef.scene.entities[i];
5156                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5157                         ent->model->DrawAddWaterPlanes(ent);
5158         }
5159 }
5160
5161 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}};
5162
5163 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5164 {
5165         if (r_hdr_irisadaptation.integer)
5166         {
5167                 vec3_t p;
5168                 vec3_t ambient;
5169                 vec3_t diffuse;
5170                 vec3_t diffusenormal;
5171                 vec3_t forward;
5172                 vec_t brightness = 0.0f;
5173                 vec_t goal;
5174                 vec_t current;
5175                 vec_t d;
5176                 int c;
5177                 VectorCopy(r_refdef.view.forward, forward);
5178                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5179                 {
5180                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5181                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5182                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5183                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5184                         d = DotProduct(forward, diffusenormal);
5185                         brightness += VectorLength(ambient);
5186                         if (d > 0)
5187                                 brightness += d * VectorLength(diffuse);
5188                 }
5189                 brightness *= 1.0f / c;
5190                 brightness += 0.00001f; // make sure it's never zero
5191                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5192                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5193                 current = r_hdr_irisadaptation_value.value;
5194                 if (current < goal)
5195                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5196                 else if (current > goal)
5197                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5198                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5199                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5200         }
5201         else if (r_hdr_irisadaptation_value.value != 1.0f)
5202                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5203 }
5204
5205 static void R_View_SetFrustum(const int *scissor)
5206 {
5207         int i;
5208         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5209         vec3_t forward, left, up, origin, v;
5210
5211         if(scissor)
5212         {
5213                 // flipped x coordinates (because x points left here)
5214                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5215                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5216
5217                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5218                 switch(vid.renderpath)
5219                 {
5220                         case RENDERPATH_D3D9:
5221                         case RENDERPATH_D3D10:
5222                         case RENDERPATH_D3D11:
5223                                 // non-flipped y coordinates
5224                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5225                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5226                                 break;
5227                         case RENDERPATH_SOFT:
5228                         case RENDERPATH_GL11:
5229                         case RENDERPATH_GL13:
5230                         case RENDERPATH_GL20:
5231                         case RENDERPATH_GLES1:
5232                         case RENDERPATH_GLES2:
5233                                 // non-flipped y coordinates
5234                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5235                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5236                                 break;
5237                 }
5238         }
5239
5240         // we can't trust r_refdef.view.forward and friends in reflected scenes
5241         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5242
5243 #if 0
5244         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5245         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5246         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5247         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5248         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5249         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5250         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5251         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5252         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5253         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5254         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5255         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5256 #endif
5257
5258 #if 0
5259         zNear = r_refdef.nearclip;
5260         nudge = 1.0 - 1.0 / (1<<23);
5261         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5262         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5263         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5264         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5265         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5266         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5267         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5268         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5269 #endif
5270
5271
5272
5273 #if 0
5274         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5275         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5276         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5277         r_refdef.view.frustum[0].dist = m[15] - m[12];
5278
5279         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5280         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5281         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5282         r_refdef.view.frustum[1].dist = m[15] + m[12];
5283
5284         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5285         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5286         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5287         r_refdef.view.frustum[2].dist = m[15] - m[13];
5288
5289         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5290         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5291         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5292         r_refdef.view.frustum[3].dist = m[15] + m[13];
5293
5294         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5295         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5296         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5297         r_refdef.view.frustum[4].dist = m[15] - m[14];
5298
5299         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5300         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5301         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5302         r_refdef.view.frustum[5].dist = m[15] + m[14];
5303 #endif
5304
5305         if (r_refdef.view.useperspective)
5306         {
5307                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5308                 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]);
5309                 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]);
5310                 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]);
5311                 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]);
5312
5313                 // then the normals from the corners relative to origin
5314                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5315                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5316                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5317                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5318
5319                 // in a NORMAL view, forward cross left == up
5320                 // in a REFLECTED view, forward cross left == down
5321                 // so our cross products above need to be adjusted for a left handed coordinate system
5322                 CrossProduct(forward, left, v);
5323                 if(DotProduct(v, up) < 0)
5324                 {
5325                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5326                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5327                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5328                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5329                 }
5330
5331                 // Leaving those out was a mistake, those were in the old code, and they
5332                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5333                 // I couldn't reproduce it after adding those normalizations. --blub
5334                 VectorNormalize(r_refdef.view.frustum[0].normal);
5335                 VectorNormalize(r_refdef.view.frustum[1].normal);
5336                 VectorNormalize(r_refdef.view.frustum[2].normal);
5337                 VectorNormalize(r_refdef.view.frustum[3].normal);
5338
5339                 // make the corners absolute
5340                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5341                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5342                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5343                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5344
5345                 // one more normal
5346                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5347
5348                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5349                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5350                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5351                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5352                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5353         }
5354         else
5355         {
5356                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5357                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5358                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5359                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5360                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5361                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5362                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5363                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5364                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5365                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5366         }
5367         r_refdef.view.numfrustumplanes = 5;
5368
5369         if (r_refdef.view.useclipplane)
5370         {
5371                 r_refdef.view.numfrustumplanes = 6;
5372                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5373         }
5374
5375         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5376                 PlaneClassify(r_refdef.view.frustum + i);
5377
5378         // LordHavoc: note to all quake engine coders, Quake had a special case
5379         // for 90 degrees which assumed a square view (wrong), so I removed it,
5380         // Quake2 has it disabled as well.
5381
5382         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5383         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5384         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5385         //PlaneClassify(&frustum[0]);
5386
5387         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5388         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5389         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5390         //PlaneClassify(&frustum[1]);
5391
5392         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5393         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5394         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5395         //PlaneClassify(&frustum[2]);
5396
5397         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5398         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5399         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5400         //PlaneClassify(&frustum[3]);
5401
5402         // nearclip plane
5403         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5404         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5405         //PlaneClassify(&frustum[4]);
5406 }
5407
5408 static void R_View_UpdateWithScissor(const int *myscissor)
5409 {
5410         R_Main_ResizeViewCache();
5411         R_View_SetFrustum(myscissor);
5412         R_View_WorldVisibility(r_refdef.view.useclipplane);
5413         R_View_UpdateEntityVisible();
5414         R_View_UpdateEntityLighting();
5415 }
5416
5417 static void R_View_Update(void)
5418 {
5419         R_Main_ResizeViewCache();
5420         R_View_SetFrustum(NULL);
5421         R_View_WorldVisibility(r_refdef.view.useclipplane);
5422         R_View_UpdateEntityVisible();
5423         R_View_UpdateEntityLighting();
5424 }
5425
5426 float viewscalefpsadjusted = 1.0f;
5427
5428 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5429 {
5430         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5431         scale = bound(0.03125f, scale, 1.0f);
5432         *outwidth = (int)ceil(width * scale);
5433         *outheight = (int)ceil(height * scale);
5434 }
5435
5436 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5437 {
5438         const float *customclipplane = NULL;
5439         float plane[4];
5440         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5441         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5442         {
5443                 // LordHavoc: couldn't figure out how to make this approach the
5444                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5445                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5446                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5447                         dist = r_refdef.view.clipplane.dist;
5448                 plane[0] = r_refdef.view.clipplane.normal[0];
5449                 plane[1] = r_refdef.view.clipplane.normal[1];
5450                 plane[2] = r_refdef.view.clipplane.normal[2];
5451                 plane[3] = -dist;
5452                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5453         }
5454
5455         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5456         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5457
5458         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5459         if (!r_refdef.view.useperspective)
5460                 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);
5461         else if (vid.stencil && r_useinfinitefarclip.integer)
5462                 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);
5463         else
5464                 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);
5465         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5466         R_SetViewport(&r_refdef.view.viewport);
5467         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5468         {
5469                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5470                 float screenplane[4];
5471                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5472                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5473                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5474                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5475                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5476         }
5477 }
5478
5479 void R_EntityMatrix(const matrix4x4_t *matrix)
5480 {
5481         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5482         {
5483                 gl_modelmatrixchanged = false;
5484                 gl_modelmatrix = *matrix;
5485                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5486                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5487                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5488                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5489                 CHECKGLERROR
5490                 switch(vid.renderpath)
5491                 {
5492                 case RENDERPATH_D3D9:
5493 #ifdef SUPPORTD3D
5494                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5495                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5496 #endif
5497                         break;
5498                 case RENDERPATH_D3D10:
5499                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5500                         break;
5501                 case RENDERPATH_D3D11:
5502                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5503                         break;
5504                 case RENDERPATH_GL11:
5505                 case RENDERPATH_GL13:
5506                 case RENDERPATH_GLES1:
5507                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5508                         break;
5509                 case RENDERPATH_SOFT:
5510                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5511                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5512                         break;
5513                 case RENDERPATH_GL20:
5514                 case RENDERPATH_GLES2:
5515                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5516                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5517                         break;
5518                 }
5519         }
5520 }
5521
5522 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5523 {
5524         r_viewport_t viewport;
5525
5526         CHECKGLERROR
5527
5528         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5529         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);
5530         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5531         R_SetViewport(&viewport);
5532         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5533         GL_Color(1, 1, 1, 1);
5534         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5535         GL_BlendFunc(GL_ONE, GL_ZERO);
5536         GL_ScissorTest(false);
5537         GL_DepthMask(false);
5538         GL_DepthRange(0, 1);
5539         GL_DepthTest(false);
5540         GL_DepthFunc(GL_LEQUAL);
5541         R_EntityMatrix(&identitymatrix);
5542         R_Mesh_ResetTextureState();
5543         GL_PolygonOffset(0, 0);
5544         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5545         switch(vid.renderpath)
5546         {
5547         case RENDERPATH_GL11:
5548         case RENDERPATH_GL13:
5549         case RENDERPATH_GL20:
5550         case RENDERPATH_GLES1:
5551         case RENDERPATH_GLES2:
5552                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5553                 break;
5554         case RENDERPATH_D3D9:
5555         case RENDERPATH_D3D10:
5556         case RENDERPATH_D3D11:
5557         case RENDERPATH_SOFT:
5558                 break;
5559         }
5560         GL_CullFace(GL_NONE);
5561
5562         CHECKGLERROR
5563 }
5564
5565 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5566 {
5567         DrawQ_Finish();
5568
5569         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5570 }
5571
5572 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5573 {
5574         DrawQ_Finish();
5575
5576         R_SetupView(true, fbo, depthtexture, colortexture);
5577         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5578         GL_Color(1, 1, 1, 1);
5579         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5580         GL_BlendFunc(GL_ONE, GL_ZERO);
5581         GL_ScissorTest(true);
5582         GL_DepthMask(true);
5583         GL_DepthRange(0, 1);
5584         GL_DepthTest(true);
5585         GL_DepthFunc(GL_LEQUAL);
5586         R_EntityMatrix(&identitymatrix);
5587         R_Mesh_ResetTextureState();
5588         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5589         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5590         switch(vid.renderpath)
5591         {
5592         case RENDERPATH_GL11:
5593         case RENDERPATH_GL13:
5594         case RENDERPATH_GL20:
5595         case RENDERPATH_GLES1:
5596         case RENDERPATH_GLES2:
5597                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5598                 break;
5599         case RENDERPATH_D3D9:
5600         case RENDERPATH_D3D10:
5601         case RENDERPATH_D3D11:
5602         case RENDERPATH_SOFT:
5603                 break;
5604         }
5605         GL_CullFace(r_refdef.view.cullface_back);
5606 }
5607
5608 /*
5609 ================
5610 R_RenderView_UpdateViewVectors
5611 ================
5612 */
5613 void R_RenderView_UpdateViewVectors(void)
5614 {
5615         // break apart the view matrix into vectors for various purposes
5616         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5617         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5618         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5619         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5620         // make an inverted copy of the view matrix for tracking sprites
5621         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5622 }
5623
5624 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5625 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5626
5627 static void R_Water_StartFrame(void)
5628 {
5629         int i;
5630         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5631         r_waterstate_waterplane_t *p;
5632         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;
5633
5634         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5635                 return;
5636
5637         switch(vid.renderpath)
5638         {
5639         case RENDERPATH_GL20:
5640         case RENDERPATH_D3D9:
5641         case RENDERPATH_D3D10:
5642         case RENDERPATH_D3D11:
5643         case RENDERPATH_SOFT:
5644         case RENDERPATH_GLES2:
5645                 break;
5646         case RENDERPATH_GL11:
5647         case RENDERPATH_GL13:
5648         case RENDERPATH_GLES1:
5649                 return;
5650         }
5651
5652         // set waterwidth and waterheight to the water resolution that will be
5653         // used (often less than the screen resolution for faster rendering)
5654         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5655
5656         // calculate desired texture sizes
5657         // can't use water if the card does not support the texture size
5658         if (!r_water.integer || r_showsurfaces.integer)
5659                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5660         else if (vid.support.arb_texture_non_power_of_two)
5661         {
5662                 texturewidth = waterwidth;
5663                 textureheight = waterheight;
5664                 camerawidth = waterwidth;
5665                 cameraheight = waterheight;
5666         }
5667         else
5668         {
5669                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5670                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5671                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5672                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5673         }
5674
5675         // allocate textures as needed
5676         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))
5677         {
5678                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5679                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5680                 {
5681                         if (p->texture_refraction)
5682                                 R_FreeTexture(p->texture_refraction);
5683                         p->texture_refraction = NULL;
5684                         if (p->fbo_refraction)
5685                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5686                         p->fbo_refraction = 0;
5687                         if (p->texture_reflection)
5688                                 R_FreeTexture(p->texture_reflection);
5689                         p->texture_reflection = NULL;
5690                         if (p->fbo_reflection)
5691                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5692                         p->fbo_reflection = 0;
5693                         if (p->texture_camera)
5694                                 R_FreeTexture(p->texture_camera);
5695                         p->texture_camera = NULL;
5696                         if (p->fbo_camera)
5697                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5698                         p->fbo_camera = 0;
5699                 }
5700                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5701                 r_fb.water.texturewidth = texturewidth;
5702                 r_fb.water.textureheight = textureheight;
5703                 r_fb.water.camerawidth = camerawidth;
5704                 r_fb.water.cameraheight = cameraheight;
5705         }
5706
5707         if (r_fb.water.texturewidth)
5708         {
5709                 int scaledwidth, scaledheight;
5710
5711                 r_fb.water.enabled = true;
5712
5713                 // water resolution is usually reduced
5714                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5715                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5716                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5717
5718                 // set up variables that will be used in shader setup
5719                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5720                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5721                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5722                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5723         }
5724
5725         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5726         r_fb.water.numwaterplanes = 0;
5727 }
5728
5729 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5730 {
5731         int planeindex, bestplaneindex, vertexindex;
5732         vec3_t mins, maxs, normal, center, v, n;
5733         vec_t planescore, bestplanescore;
5734         mplane_t plane;
5735         r_waterstate_waterplane_t *p;
5736         texture_t *t = R_GetCurrentTexture(surface->texture);
5737
5738         rsurface.texture = t;
5739         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5740         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5741         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5742                 return;
5743         // average the vertex normals, find the surface bounds (after deformvertexes)
5744         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5745         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5746         VectorCopy(n, normal);
5747         VectorCopy(v, mins);
5748         VectorCopy(v, maxs);
5749         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5750         {
5751                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5752                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5753                 VectorAdd(normal, n, normal);
5754                 mins[0] = min(mins[0], v[0]);
5755                 mins[1] = min(mins[1], v[1]);
5756                 mins[2] = min(mins[2], v[2]);
5757                 maxs[0] = max(maxs[0], v[0]);
5758                 maxs[1] = max(maxs[1], v[1]);
5759                 maxs[2] = max(maxs[2], v[2]);
5760         }
5761         VectorNormalize(normal);
5762         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5763
5764         VectorCopy(normal, plane.normal);
5765         VectorNormalize(plane.normal);
5766         plane.dist = DotProduct(center, plane.normal);
5767         PlaneClassify(&plane);
5768         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5769         {
5770                 // skip backfaces (except if nocullface is set)
5771 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5772 //                      return;
5773                 VectorNegate(plane.normal, plane.normal);
5774                 plane.dist *= -1;
5775                 PlaneClassify(&plane);
5776         }
5777
5778
5779         // find a matching plane if there is one
5780         bestplaneindex = -1;
5781         bestplanescore = 1048576.0f;
5782         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5783         {
5784                 if(p->camera_entity == t->camera_entity)
5785                 {
5786                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5787                         if (bestplaneindex < 0 || bestplanescore > planescore)
5788                         {
5789                                 bestplaneindex = planeindex;
5790                                 bestplanescore = planescore;
5791                         }
5792                 }
5793         }
5794         planeindex = bestplaneindex;
5795         p = r_fb.water.waterplanes + planeindex;
5796
5797         // if this surface does not fit any known plane rendered this frame, add one
5798         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5799         {
5800                 // store the new plane
5801                 planeindex = r_fb.water.numwaterplanes++;
5802                 p = r_fb.water.waterplanes + planeindex;
5803                 p->plane = plane;
5804                 // clear materialflags and pvs
5805                 p->materialflags = 0;
5806                 p->pvsvalid = false;
5807                 p->camera_entity = t->camera_entity;
5808                 VectorCopy(mins, p->mins);
5809                 VectorCopy(maxs, p->maxs);
5810         }
5811         else
5812         {
5813                 // merge mins/maxs when we're adding this surface to the plane
5814                 p->mins[0] = min(p->mins[0], mins[0]);
5815                 p->mins[1] = min(p->mins[1], mins[1]);
5816                 p->mins[2] = min(p->mins[2], mins[2]);
5817                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5818                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5819                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5820         }
5821         // merge this surface's materialflags into the waterplane
5822         p->materialflags |= t->currentmaterialflags;
5823         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5824         {
5825                 // merge this surface's PVS into the waterplane
5826                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5827                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5828                 {
5829                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5830                         p->pvsvalid = true;
5831                 }
5832         }
5833 }
5834
5835 extern cvar_t r_drawparticles;
5836 extern cvar_t r_drawdecals;
5837
5838 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5839 {
5840         int myscissor[4];
5841         r_refdef_view_t originalview;
5842         r_refdef_view_t myview;
5843         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;
5844         r_waterstate_waterplane_t *p;
5845         vec3_t visorigin;
5846         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;
5847         char vabuf[1024];
5848
5849         originalview = r_refdef.view;
5850
5851         // lowquality hack, temporarily shut down some cvars and restore afterwards
5852         qualityreduction = r_water_lowquality.integer;
5853         if (qualityreduction > 0)
5854         {
5855                 if (qualityreduction >= 1)
5856                 {
5857                         old_r_shadows = r_shadows.integer;
5858                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5859                         old_r_dlight = r_shadow_realtime_dlight.integer;
5860                         Cvar_SetValueQuick(&r_shadows, 0);
5861                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5862                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5863                 }
5864                 if (qualityreduction >= 2)
5865                 {
5866                         old_r_dynamic = r_dynamic.integer;
5867                         old_r_particles = r_drawparticles.integer;
5868                         old_r_decals = r_drawdecals.integer;
5869                         Cvar_SetValueQuick(&r_dynamic, 0);
5870                         Cvar_SetValueQuick(&r_drawparticles, 0);
5871                         Cvar_SetValueQuick(&r_drawdecals, 0);
5872                 }
5873         }
5874
5875         // make sure enough textures are allocated
5876         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5877         {
5878                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5879                 {
5880                         if (!p->texture_refraction)
5881                                 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);
5882                         if (!p->texture_refraction)
5883                                 goto error;
5884                         if (usewaterfbo)
5885                         {
5886                                 if (r_fb.water.depthtexture == NULL)
5887                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5888                                 if (p->fbo_refraction == 0)
5889                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5890                         }
5891                 }
5892                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5893                 {
5894                         if (!p->texture_camera)
5895                                 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);
5896                         if (!p->texture_camera)
5897                                 goto error;
5898                         if (usewaterfbo)
5899                         {
5900                                 if (r_fb.water.depthtexture == NULL)
5901                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5902                                 if (p->fbo_camera == 0)
5903                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5904                         }
5905                 }
5906
5907                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5908                 {
5909                         if (!p->texture_reflection)
5910                                 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);
5911                         if (!p->texture_reflection)
5912                                 goto error;
5913                         if (usewaterfbo)
5914                         {
5915                                 if (r_fb.water.depthtexture == NULL)
5916                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5917                                 if (p->fbo_reflection == 0)
5918                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5919                         }
5920                 }
5921         }
5922
5923         // render views
5924         r_refdef.view = originalview;
5925         r_refdef.view.showdebug = false;
5926         r_refdef.view.width = r_fb.water.waterwidth;
5927         r_refdef.view.height = r_fb.water.waterheight;
5928         r_refdef.view.useclipplane = true;
5929         myview = r_refdef.view;
5930         r_fb.water.renderingscene = true;
5931         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5932         {
5933                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5934                 {
5935                         r_refdef.view = myview;
5936                         if(r_water_scissormode.integer)
5937                         {
5938                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5939                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5940                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5941                         }
5942
5943                         // render reflected scene and copy into texture
5944                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5945                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5946                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5947                         r_refdef.view.clipplane = p->plane;
5948                         // reverse the cullface settings for this render
5949                         r_refdef.view.cullface_front = GL_FRONT;
5950                         r_refdef.view.cullface_back = GL_BACK;
5951                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5952                         {
5953                                 r_refdef.view.usecustompvs = true;
5954                                 if (p->pvsvalid)
5955                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5956                                 else
5957                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5958                         }
5959
5960                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5961                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5962                         R_ClearScreen(r_refdef.fogenabled);
5963                         if(r_water_scissormode.integer & 2)
5964                                 R_View_UpdateWithScissor(myscissor);
5965                         else
5966                                 R_View_Update();
5967                         R_AnimCache_CacheVisibleEntities();
5968                         if(r_water_scissormode.integer & 1)
5969                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5970                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5971
5972                         if (!p->fbo_reflection)
5973                                 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);
5974                         r_fb.water.hideplayer = false;
5975                 }
5976
5977                 // render the normal view scene and copy into texture
5978                 // (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)
5979                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5980                 {
5981                         r_refdef.view = myview;
5982                         if(r_water_scissormode.integer)
5983                         {
5984                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5985                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5986                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5987                         }
5988
5989                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5990
5991                         r_refdef.view.clipplane = p->plane;
5992                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5993                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5994
5995                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5996                         {
5997                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5998                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5999                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6000                                 R_RenderView_UpdateViewVectors();
6001                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6002                                 {
6003                                         r_refdef.view.usecustompvs = true;
6004                                         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);
6005                                 }
6006                         }
6007
6008                         PlaneClassify(&r_refdef.view.clipplane);
6009
6010                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6011                         R_ClearScreen(r_refdef.fogenabled);
6012                         if(r_water_scissormode.integer & 2)
6013                                 R_View_UpdateWithScissor(myscissor);
6014                         else
6015                                 R_View_Update();
6016                         R_AnimCache_CacheVisibleEntities();
6017                         if(r_water_scissormode.integer & 1)
6018                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6019                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6020
6021                         if (!p->fbo_refraction)
6022                                 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);
6023                         r_fb.water.hideplayer = false;
6024                 }
6025                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6026                 {
6027                         r_refdef.view = myview;
6028
6029                         r_refdef.view.clipplane = p->plane;
6030                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6031                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6032
6033                         r_refdef.view.width = r_fb.water.camerawidth;
6034                         r_refdef.view.height = r_fb.water.cameraheight;
6035                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6036                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6037                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6038                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6039
6040                         if(p->camera_entity)
6041                         {
6042                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6043                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6044                         }
6045
6046                         // note: all of the view is used for displaying... so
6047                         // there is no use in scissoring
6048
6049                         // reverse the cullface settings for this render
6050                         r_refdef.view.cullface_front = GL_FRONT;
6051                         r_refdef.view.cullface_back = GL_BACK;
6052                         // also reverse the view matrix
6053                         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
6054                         R_RenderView_UpdateViewVectors();
6055                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6056                         {
6057                                 r_refdef.view.usecustompvs = true;
6058                                 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);
6059                         }
6060                         
6061                         // camera needs no clipplane
6062                         r_refdef.view.useclipplane = false;
6063
6064                         PlaneClassify(&r_refdef.view.clipplane);
6065
6066                         r_fb.water.hideplayer = false;
6067
6068                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6069                         R_ClearScreen(r_refdef.fogenabled);
6070                         R_View_Update();
6071                         R_AnimCache_CacheVisibleEntities();
6072                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6073
6074                         if (!p->fbo_camera)
6075                                 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);
6076                         r_fb.water.hideplayer = false;
6077                 }
6078
6079         }
6080         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6081         r_fb.water.renderingscene = false;
6082         r_refdef.view = originalview;
6083         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6084         if (!r_fb.water.depthtexture)
6085                 R_ClearScreen(r_refdef.fogenabled);
6086         R_View_Update();
6087         R_AnimCache_CacheVisibleEntities();
6088         goto finish;
6089 error:
6090         r_refdef.view = originalview;
6091         r_fb.water.renderingscene = false;
6092         Cvar_SetValueQuick(&r_water, 0);
6093         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6094 finish:
6095         // lowquality hack, restore cvars
6096         if (qualityreduction > 0)
6097         {
6098                 if (qualityreduction >= 1)
6099                 {
6100                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6101                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6102                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6103                 }
6104                 if (qualityreduction >= 2)
6105                 {
6106                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6107                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6108                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6109                 }
6110         }
6111 }
6112
6113 static void R_Bloom_StartFrame(void)
6114 {
6115         int i;
6116         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6117         int viewwidth, viewheight;
6118         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6119         textype_t textype = TEXTYPE_COLORBUFFER;
6120
6121         switch (vid.renderpath)
6122         {
6123         case RENDERPATH_GL20:
6124                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6125                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6126                 {
6127                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6128                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6129                 }
6130                 break;
6131         case RENDERPATH_GL11:
6132         case RENDERPATH_GL13:
6133         case RENDERPATH_GLES1:
6134         case RENDERPATH_GLES2:
6135         case RENDERPATH_D3D9:
6136         case RENDERPATH_D3D10:
6137         case RENDERPATH_D3D11:
6138                 r_fb.usedepthtextures = false;
6139                 break;
6140         case RENDERPATH_SOFT:
6141                 r_fb.usedepthtextures = true;
6142                 break;
6143         }
6144
6145         if (r_viewscale_fpsscaling.integer)
6146         {
6147                 double actualframetime;
6148                 double targetframetime;
6149                 double adjust;
6150                 actualframetime = r_refdef.lastdrawscreentime;
6151                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6152                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6153                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6154                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6155                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6156                 viewscalefpsadjusted += adjust;
6157                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6158         }
6159         else
6160                 viewscalefpsadjusted = 1.0f;
6161
6162         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6163
6164         switch(vid.renderpath)
6165         {
6166         case RENDERPATH_GL20:
6167         case RENDERPATH_D3D9:
6168         case RENDERPATH_D3D10:
6169         case RENDERPATH_D3D11:
6170         case RENDERPATH_SOFT:
6171         case RENDERPATH_GLES2:
6172                 break;
6173         case RENDERPATH_GL11:
6174         case RENDERPATH_GL13:
6175         case RENDERPATH_GLES1:
6176                 return;
6177         }
6178
6179         // set bloomwidth and bloomheight to the bloom resolution that will be
6180         // used (often less than the screen resolution for faster rendering)
6181         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6182         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6183         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6184         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6185         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6186
6187         // calculate desired texture sizes
6188         if (vid.support.arb_texture_non_power_of_two)
6189         {
6190                 screentexturewidth = vid.width;
6191                 screentextureheight = vid.height;
6192                 bloomtexturewidth = r_fb.bloomwidth;
6193                 bloomtextureheight = r_fb.bloomheight;
6194         }
6195         else
6196         {
6197                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6198                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6199                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6200                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6201         }
6202
6203         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))
6204         {
6205                 Cvar_SetValueQuick(&r_bloom, 0);
6206                 Cvar_SetValueQuick(&r_motionblur, 0);
6207                 Cvar_SetValueQuick(&r_damageblur, 0);
6208         }
6209
6210         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6211          && !r_bloom.integer
6212          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6213          && !useviewfbo
6214          && r_viewscale.value == 1.0f
6215          && !r_viewscale_fpsscaling.integer)
6216                 screentexturewidth = screentextureheight = 0;
6217         if (!r_bloom.integer)
6218                 bloomtexturewidth = bloomtextureheight = 0;
6219
6220         // allocate textures as needed
6221         if (r_fb.screentexturewidth != screentexturewidth
6222          || r_fb.screentextureheight != screentextureheight
6223          || r_fb.bloomtexturewidth != bloomtexturewidth
6224          || r_fb.bloomtextureheight != bloomtextureheight
6225          || r_fb.textype != textype
6226          || useviewfbo != (r_fb.fbo != 0))
6227         {
6228                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6229                 {
6230                         if (r_fb.bloomtexture[i])
6231                                 R_FreeTexture(r_fb.bloomtexture[i]);
6232                         r_fb.bloomtexture[i] = NULL;
6233
6234                         if (r_fb.bloomfbo[i])
6235                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6236                         r_fb.bloomfbo[i] = 0;
6237                 }
6238
6239                 if (r_fb.fbo)
6240                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6241                 r_fb.fbo = 0;
6242
6243                 if (r_fb.colortexture)
6244                         R_FreeTexture(r_fb.colortexture);
6245                 r_fb.colortexture = NULL;
6246
6247                 if (r_fb.depthtexture)
6248                         R_FreeTexture(r_fb.depthtexture);
6249                 r_fb.depthtexture = NULL;
6250
6251                 if (r_fb.ghosttexture)
6252                         R_FreeTexture(r_fb.ghosttexture);
6253                 r_fb.ghosttexture = NULL;
6254
6255                 r_fb.screentexturewidth = screentexturewidth;
6256                 r_fb.screentextureheight = screentextureheight;
6257                 r_fb.bloomtexturewidth = bloomtexturewidth;
6258                 r_fb.bloomtextureheight = bloomtextureheight;
6259                 r_fb.textype = textype;
6260
6261                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6262                 {
6263                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6264                                 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);
6265                         r_fb.ghosttexture_valid = false;
6266                         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);
6267                         if (useviewfbo)
6268                         {
6269                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6270                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6271                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6272                         }
6273                 }
6274
6275                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6276                 {
6277                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6278                         {
6279                                 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);
6280                                 if (useviewfbo)
6281                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6282                         }
6283                 }
6284         }
6285
6286         // bloom texture is a different resolution
6287         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6288         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6289         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6290         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6291         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6292
6293         // set up a texcoord array for the full resolution screen image
6294         // (we have to keep this around to copy back during final render)
6295         r_fb.screentexcoord2f[0] = 0;
6296         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6297         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6298         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6299         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6300         r_fb.screentexcoord2f[5] = 0;
6301         r_fb.screentexcoord2f[6] = 0;
6302         r_fb.screentexcoord2f[7] = 0;
6303
6304         if(r_fb.fbo) 
6305         {
6306                 for (i = 1;i < 8;i += 2)
6307                 {
6308                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6309                 }
6310         }
6311
6312         // set up a texcoord array for the reduced resolution bloom image
6313         // (which will be additive blended over the screen image)
6314         r_fb.bloomtexcoord2f[0] = 0;
6315         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6316         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6317         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6318         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6319         r_fb.bloomtexcoord2f[5] = 0;
6320         r_fb.bloomtexcoord2f[6] = 0;
6321         r_fb.bloomtexcoord2f[7] = 0;
6322
6323         switch(vid.renderpath)
6324         {
6325         case RENDERPATH_GL11:
6326         case RENDERPATH_GL13:
6327         case RENDERPATH_GL20:
6328         case RENDERPATH_SOFT:
6329         case RENDERPATH_GLES1:
6330         case RENDERPATH_GLES2:
6331                 break;
6332         case RENDERPATH_D3D9:
6333         case RENDERPATH_D3D10:
6334         case RENDERPATH_D3D11:
6335                 for (i = 0;i < 4;i++)
6336                 {
6337                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6338                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6339                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6340                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6341                 }
6342                 break;
6343         }
6344
6345         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6346
6347         if (r_fb.fbo)
6348                 r_refdef.view.clear = true;
6349 }
6350
6351 static void R_Bloom_MakeTexture(void)
6352 {
6353         int x, range, dir;
6354         float xoffset, yoffset, r, brighten;
6355         rtexture_t *intex;
6356         float colorscale = r_bloom_colorscale.value;
6357
6358         r_refdef.stats[r_stat_bloom]++;
6359     
6360 #if 0
6361     // this copy is unnecessary since it happens in R_BlendView already
6362         if (!r_fb.fbo)
6363         {
6364                 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);
6365                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6366         }
6367 #endif
6368
6369         // scale down screen texture to the bloom texture size
6370         CHECKGLERROR
6371         r_fb.bloomindex = 0;
6372         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6373         R_SetViewport(&r_fb.bloomviewport);
6374         GL_DepthTest(false);
6375         GL_BlendFunc(GL_ONE, GL_ZERO);
6376         GL_Color(colorscale, colorscale, colorscale, 1);
6377         // 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...
6378         switch(vid.renderpath)
6379         {
6380         case RENDERPATH_GL11:
6381         case RENDERPATH_GL13:
6382         case RENDERPATH_GL20:
6383         case RENDERPATH_GLES1:
6384         case RENDERPATH_GLES2:
6385         case RENDERPATH_SOFT:
6386                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6387                 break;
6388         case RENDERPATH_D3D9:
6389         case RENDERPATH_D3D10:
6390         case RENDERPATH_D3D11:
6391                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6392                 break;
6393         }
6394         // TODO: do boxfilter scale-down in shader?
6395         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6396         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6397         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6398
6399         // we now have a properly scaled bloom image
6400         if (!r_fb.bloomfbo[r_fb.bloomindex])
6401         {
6402                 // copy it into the bloom texture
6403                 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);
6404                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6405         }
6406
6407         // multiply bloom image by itself as many times as desired
6408         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6409         {
6410                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6411                 r_fb.bloomindex ^= 1;
6412                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6413                 x *= 2;
6414                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6415                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6416                 {
6417                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6418                         GL_Color(r,r,r,1); // apply fix factor
6419                 }
6420                 else
6421                 {
6422                         if(x <= 2)
6423                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6424                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6425                         GL_Color(1,1,1,1); // no fix factor supported here
6426                 }
6427                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6428                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6429                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6430                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6431
6432                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6433                 {
6434                         // copy the darkened image to a texture
6435                         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);
6436                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6437                 }
6438         }
6439
6440         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6441         brighten = r_bloom_brighten.value;
6442         brighten = sqrt(brighten);
6443         if(range >= 1)
6444                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6445
6446         for (dir = 0;dir < 2;dir++)
6447         {
6448                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6449                 r_fb.bloomindex ^= 1;
6450                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6451                 // blend on at multiple vertical offsets to achieve a vertical blur
6452                 // TODO: do offset blends using GLSL
6453                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6454                 GL_BlendFunc(GL_ONE, GL_ZERO);
6455                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6456                 for (x = -range;x <= range;x++)
6457                 {
6458                         if (!dir){xoffset = 0;yoffset = x;}
6459                         else {xoffset = x;yoffset = 0;}
6460                         xoffset /= (float)r_fb.bloomtexturewidth;
6461                         yoffset /= (float)r_fb.bloomtextureheight;
6462                         // compute a texcoord array with the specified x and y offset
6463                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6464                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6465                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6466                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6467                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6468                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6469                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6470                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6471                         // this r value looks like a 'dot' particle, fading sharply to
6472                         // black at the edges
6473                         // (probably not realistic but looks good enough)
6474                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6475                         //r = brighten/(range*2+1);
6476                         r = brighten / (range * 2 + 1);
6477                         if(range >= 1)
6478                                 r *= (1 - x*x/(float)(range*range));
6479                         GL_Color(r, r, r, 1);
6480                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6481                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6482                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6483                         GL_BlendFunc(GL_ONE, GL_ONE);
6484                 }
6485
6486                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6487                 {
6488                         // copy the vertically or horizontally blurred bloom view to a texture
6489                         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);
6490                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6491                 }
6492         }
6493 }
6494
6495 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6496 {
6497         unsigned int permutation;
6498         float uservecs[4][4];
6499
6500         R_EntityMatrix(&identitymatrix);
6501
6502         switch (vid.renderpath)
6503         {
6504         case RENDERPATH_GL20:
6505         case RENDERPATH_D3D9:
6506         case RENDERPATH_D3D10:
6507         case RENDERPATH_D3D11:
6508         case RENDERPATH_SOFT:
6509         case RENDERPATH_GLES2:
6510                 permutation =
6511                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6512                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6513                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6514                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6515                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6516
6517                 if (r_fb.colortexture)
6518                 {
6519                         if (!r_fb.fbo)
6520                         {
6521                                 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);
6522                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6523                         }
6524
6525                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6526                         {
6527                                 // declare variables
6528                                 float blur_factor, blur_mouseaccel, blur_velocity;
6529                                 static float blur_average; 
6530                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6531
6532                                 // set a goal for the factoring
6533                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6534                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6535                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6536                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6537                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6538                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6539
6540                                 // from the goal, pick an averaged value between goal and last value
6541                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6542                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6543
6544                                 // enforce minimum amount of blur 
6545                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6546
6547                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6548
6549                                 // calculate values into a standard alpha
6550                                 cl.motionbluralpha = 1 - exp(-
6551                                                 (
6552                                                  (r_motionblur.value * blur_factor / 80)
6553                                                  +
6554                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6555                                                 )
6556                                                 /
6557                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6558                                           );
6559
6560                                 // randomization for the blur value to combat persistent ghosting
6561                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6562                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6563
6564                                 // apply the blur
6565                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6566                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6567                                 {
6568                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6569                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6570                                         switch(vid.renderpath)
6571                                         {
6572                                         case RENDERPATH_GL11:
6573                                         case RENDERPATH_GL13:
6574                                         case RENDERPATH_GL20:
6575                                         case RENDERPATH_GLES1:
6576                                         case RENDERPATH_GLES2:
6577                                         case RENDERPATH_SOFT:
6578                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6579                                                 break;
6580                                         case RENDERPATH_D3D9:
6581                                         case RENDERPATH_D3D10:
6582                                         case RENDERPATH_D3D11:
6583                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6584                                                 break;
6585                                         }
6586                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6587                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6588                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6589                                 }
6590
6591                                 // updates old view angles for next pass
6592                                 VectorCopy(cl.viewangles, blur_oldangles);
6593
6594                                 // copy view into the ghost texture
6595                                 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);
6596                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6597                                 r_fb.ghosttexture_valid = true;
6598                         }
6599                 }
6600                 else
6601                 {
6602                         // no r_fb.colortexture means we're rendering to the real fb
6603                         // we may still have to do view tint...
6604                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6605                         {
6606                                 // apply a color tint to the whole view
6607                                 R_ResetViewRendering2D(0, NULL, NULL);
6608                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6609                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6610                                 R_SetupShader_Generic_NoTexture(false, true);
6611                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6612                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6613                         }
6614                         break; // no screen processing, no bloom, skip it
6615                 }
6616
6617                 if (r_fb.bloomtexture[0])
6618                 {
6619                         // make the bloom texture
6620                         R_Bloom_MakeTexture();
6621                 }
6622
6623 #if _MSC_VER >= 1400
6624 #define sscanf sscanf_s
6625 #endif
6626                 memset(uservecs, 0, sizeof(uservecs));
6627                 if (r_glsl_postprocess_uservec1_enable.integer)
6628                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6629                 if (r_glsl_postprocess_uservec2_enable.integer)
6630                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6631                 if (r_glsl_postprocess_uservec3_enable.integer)
6632                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6633                 if (r_glsl_postprocess_uservec4_enable.integer)
6634                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6635
6636                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6637                 GL_Color(1, 1, 1, 1);
6638                 GL_BlendFunc(GL_ONE, GL_ZERO);
6639
6640                 switch(vid.renderpath)
6641                 {
6642                 case RENDERPATH_GL20:
6643                 case RENDERPATH_GLES2:
6644                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6645                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6646                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6647                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6648                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6649                         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]);
6650                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6651                         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]);
6652                         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]);
6653                         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]);
6654                         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]);
6655                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6656                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6657                         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);
6658                         break;
6659                 case RENDERPATH_D3D9:
6660 #ifdef SUPPORTD3D
6661                         // 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...
6662                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6663                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6664                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6665                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6666                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6667                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6668                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6669                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6670                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6671                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6672                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6673                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6674                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6675                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6676 #endif
6677                         break;
6678                 case RENDERPATH_D3D10:
6679                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6680                         break;
6681                 case RENDERPATH_D3D11:
6682                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6683                         break;
6684                 case RENDERPATH_SOFT:
6685                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6686                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6687                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6688                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6689                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6690                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6691                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6692                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6693                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6694                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6695                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6696                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6697                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6698                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6699                         break;
6700                 default:
6701                         break;
6702                 }
6703                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6704                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6705                 break;
6706         case RENDERPATH_GL11:
6707         case RENDERPATH_GL13:
6708         case RENDERPATH_GLES1:
6709                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6710                 {
6711                         // apply a color tint to the whole view
6712                         R_ResetViewRendering2D(0, NULL, NULL);
6713                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6714                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6715                         R_SetupShader_Generic_NoTexture(false, true);
6716                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6717                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6718                 }
6719                 break;
6720         }
6721 }
6722
6723 matrix4x4_t r_waterscrollmatrix;
6724
6725 void R_UpdateFog(void)
6726 {
6727         // Nehahra fog
6728         if (gamemode == GAME_NEHAHRA)
6729         {
6730                 if (gl_fogenable.integer)
6731                 {
6732                         r_refdef.oldgl_fogenable = true;
6733                         r_refdef.fog_density = gl_fogdensity.value;
6734                         r_refdef.fog_red = gl_fogred.value;
6735                         r_refdef.fog_green = gl_foggreen.value;
6736                         r_refdef.fog_blue = gl_fogblue.value;
6737                         r_refdef.fog_alpha = 1;
6738                         r_refdef.fog_start = 0;
6739                         r_refdef.fog_end = gl_skyclip.value;
6740                         r_refdef.fog_height = 1<<30;
6741                         r_refdef.fog_fadedepth = 128;
6742                 }
6743                 else if (r_refdef.oldgl_fogenable)
6744                 {
6745                         r_refdef.oldgl_fogenable = false;
6746                         r_refdef.fog_density = 0;
6747                         r_refdef.fog_red = 0;
6748                         r_refdef.fog_green = 0;
6749                         r_refdef.fog_blue = 0;
6750                         r_refdef.fog_alpha = 0;
6751                         r_refdef.fog_start = 0;
6752                         r_refdef.fog_end = 0;
6753                         r_refdef.fog_height = 1<<30;
6754                         r_refdef.fog_fadedepth = 128;
6755                 }
6756         }
6757
6758         // fog parms
6759         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6760         r_refdef.fog_start = max(0, r_refdef.fog_start);
6761         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6762
6763         if (r_refdef.fog_density && r_drawfog.integer)
6764         {
6765                 r_refdef.fogenabled = true;
6766                 // this is the point where the fog reaches 0.9986 alpha, which we
6767                 // consider a good enough cutoff point for the texture
6768                 // (0.9986 * 256 == 255.6)
6769                 if (r_fog_exp2.integer)
6770                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6771                 else
6772                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6773                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6774                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6775                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6776                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6777                         R_BuildFogHeightTexture();
6778                 // fog color was already set
6779                 // update the fog texture
6780                 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)
6781                         R_BuildFogTexture();
6782                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6783                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6784         }
6785         else
6786                 r_refdef.fogenabled = false;
6787
6788         // fog color
6789         if (r_refdef.fog_density)
6790         {
6791                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6792                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6793                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6794
6795                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6796                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6797                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6798                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6799
6800                 {
6801                         vec3_t fogvec;
6802                         VectorCopy(r_refdef.fogcolor, fogvec);
6803                         //   color.rgb *= ContrastBoost * SceneBrightness;
6804                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6805                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6806                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6807                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6808                 }
6809         }
6810 }
6811
6812 void R_UpdateVariables(void)
6813 {
6814         R_Textures_Frame();
6815
6816         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6817
6818         r_refdef.farclip = r_farclip_base.value;
6819         if (r_refdef.scene.worldmodel)
6820                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6821         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6822
6823         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6824                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6825         r_refdef.polygonfactor = 0;
6826         r_refdef.polygonoffset = 0;
6827         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6828         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6829
6830         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6831         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6832         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6833         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6834         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6835         if (FAKELIGHT_ENABLED)
6836         {
6837                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6838         }
6839         else if (r_refdef.scene.worldmodel)
6840         {
6841                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6842         }
6843         if (r_showsurfaces.integer)
6844         {
6845                 r_refdef.scene.rtworld = false;
6846                 r_refdef.scene.rtworldshadows = false;
6847                 r_refdef.scene.rtdlight = false;
6848                 r_refdef.scene.rtdlightshadows = false;
6849                 r_refdef.lightmapintensity = 0;
6850         }
6851
6852         r_gpuskeletal = false;
6853         switch(vid.renderpath)
6854         {
6855         case RENDERPATH_GL20:
6856                 r_gpuskeletal = r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6857         case RENDERPATH_D3D9:
6858         case RENDERPATH_D3D10:
6859         case RENDERPATH_D3D11:
6860         case RENDERPATH_SOFT:
6861         case RENDERPATH_GLES2:
6862                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6863                 {
6864                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6865                         {
6866                                 // build GLSL gamma texture
6867 #define RAMPWIDTH 256
6868                                 unsigned short ramp[RAMPWIDTH * 3];
6869                                 unsigned char rampbgr[RAMPWIDTH][4];
6870                                 int i;
6871
6872                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6873
6874                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6875                                 for(i = 0; i < RAMPWIDTH; ++i)
6876                                 {
6877                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6878                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6879                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6880                                         rampbgr[i][3] = 0;
6881                                 }
6882                                 if (r_texture_gammaramps)
6883                                 {
6884                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6885                                 }
6886                                 else
6887                                 {
6888                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6889                                 }
6890                         }
6891                 }
6892                 else
6893                 {
6894                         // remove GLSL gamma texture
6895                 }
6896                 break;
6897         case RENDERPATH_GL11:
6898         case RENDERPATH_GL13:
6899         case RENDERPATH_GLES1:
6900                 break;
6901         }
6902 }
6903
6904 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6905 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6906 /*
6907 ================
6908 R_SelectScene
6909 ================
6910 */
6911 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6912         if( scenetype != r_currentscenetype ) {
6913                 // store the old scenetype
6914                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6915                 r_currentscenetype = scenetype;
6916                 // move in the new scene
6917                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6918         }
6919 }
6920
6921 /*
6922 ================
6923 R_GetScenePointer
6924 ================
6925 */
6926 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6927 {
6928         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6929         if( scenetype == r_currentscenetype ) {
6930                 return &r_refdef.scene;
6931         } else {
6932                 return &r_scenes_store[ scenetype ];
6933         }
6934 }
6935
6936 static int R_SortEntities_Compare(const void *ap, const void *bp)
6937 {
6938         const entity_render_t *a = *(const entity_render_t **)ap;
6939         const entity_render_t *b = *(const entity_render_t **)bp;
6940
6941         // 1. compare model
6942         if(a->model < b->model)
6943                 return -1;
6944         if(a->model > b->model)
6945                 return +1;
6946
6947         // 2. compare skin
6948         // TODO possibly calculate the REAL skinnum here first using
6949         // skinscenes?
6950         if(a->skinnum < b->skinnum)
6951                 return -1;
6952         if(a->skinnum > b->skinnum)
6953                 return +1;
6954
6955         // everything we compared is equal
6956         return 0;
6957 }
6958 static void R_SortEntities(void)
6959 {
6960         // below or equal 2 ents, sorting never gains anything
6961         if(r_refdef.scene.numentities <= 2)
6962                 return;
6963         // sort
6964         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6965 }
6966
6967 /*
6968 ================
6969 R_RenderView
6970 ================
6971 */
6972 int dpsoftrast_test;
6973 extern cvar_t r_shadow_bouncegrid;
6974 void R_RenderView(void)
6975 {
6976         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6977         int fbo;
6978         rtexture_t *depthtexture;
6979         rtexture_t *colortexture;
6980
6981         dpsoftrast_test = r_test.integer;
6982
6983         if (r_timereport_active)
6984                 R_TimeReport("start");
6985         r_textureframe++; // used only by R_GetCurrentTexture
6986         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6987
6988         if(R_CompileShader_CheckStaticParms())
6989                 R_GLSL_Restart_f();
6990
6991         if (!r_drawentities.integer)
6992                 r_refdef.scene.numentities = 0;
6993         else if (r_sortentities.integer)
6994                 R_SortEntities();
6995
6996         R_AnimCache_ClearCache();
6997         R_FrameData_NewFrame();
6998
6999         /* adjust for stereo display */
7000         if(R_Stereo_Active())
7001         {
7002                 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);
7003                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7004         }
7005
7006         if (r_refdef.view.isoverlay)
7007         {
7008                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7009                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7010                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7011                 R_TimeReport("depthclear");
7012
7013                 r_refdef.view.showdebug = false;
7014
7015                 r_fb.water.enabled = false;
7016                 r_fb.water.numwaterplanes = 0;
7017
7018                 R_RenderScene(0, NULL, NULL);
7019
7020                 r_refdef.view.matrix = originalmatrix;
7021
7022                 CHECKGLERROR
7023                 return;
7024         }
7025
7026         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7027         {
7028                 r_refdef.view.matrix = originalmatrix;
7029                 return;
7030         }
7031
7032         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7033
7034         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7035                 // in sRGB fallback, behave similar to true sRGB: convert this
7036                 // value from linear to sRGB
7037                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7038
7039         R_RenderView_UpdateViewVectors();
7040
7041         R_Shadow_UpdateWorldLightSelection();
7042
7043         R_Bloom_StartFrame();
7044
7045         // apply bloom brightness offset
7046         if(r_fb.bloomtexture[0])
7047                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7048
7049         R_Water_StartFrame();
7050
7051         // now we probably have an fbo to render into
7052         fbo = r_fb.fbo;
7053         depthtexture = r_fb.depthtexture;
7054         colortexture = r_fb.colortexture;
7055
7056         CHECKGLERROR
7057         if (r_timereport_active)
7058                 R_TimeReport("viewsetup");
7059
7060         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7061
7062         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7063         {
7064                 R_ClearScreen(r_refdef.fogenabled);
7065                 if (r_timereport_active)
7066                         R_TimeReport("viewclear");
7067         }
7068         r_refdef.view.clear = true;
7069
7070         r_refdef.view.showdebug = true;
7071
7072         R_View_Update();
7073         if (r_timereport_active)
7074                 R_TimeReport("visibility");
7075
7076         R_AnimCache_CacheVisibleEntities();
7077         if (r_timereport_active)
7078                 R_TimeReport("animcache");
7079
7080         R_Shadow_UpdateBounceGridTexture();
7081         if (r_timereport_active && r_shadow_bouncegrid.integer)
7082                 R_TimeReport("bouncegrid");
7083
7084         r_fb.water.numwaterplanes = 0;
7085         if (r_fb.water.enabled)
7086                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7087
7088         R_RenderScene(fbo, depthtexture, colortexture);
7089         r_fb.water.numwaterplanes = 0;
7090
7091         R_BlendView(fbo, depthtexture, colortexture);
7092         if (r_timereport_active)
7093                 R_TimeReport("blendview");
7094
7095         GL_Scissor(0, 0, vid.width, vid.height);
7096         GL_ScissorTest(false);
7097
7098         r_refdef.view.matrix = originalmatrix;
7099
7100         CHECKGLERROR
7101 }
7102
7103 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7104 {
7105         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7106         {
7107                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7108                 if (r_timereport_active)
7109                         R_TimeReport("waterworld");
7110         }
7111
7112         // don't let sound skip if going slow
7113         if (r_refdef.scene.extraupdate)
7114                 S_ExtraUpdate ();
7115
7116         R_DrawModelsAddWaterPlanes();
7117         if (r_timereport_active)
7118                 R_TimeReport("watermodels");
7119
7120         if (r_fb.water.numwaterplanes)
7121         {
7122                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7123                 if (r_timereport_active)
7124                         R_TimeReport("waterscenes");
7125         }
7126 }
7127
7128 extern cvar_t cl_locs_show;
7129 static void R_DrawLocs(void);
7130 static void R_DrawEntityBBoxes(void);
7131 static void R_DrawModelDecals(void);
7132 extern cvar_t cl_decals_newsystem;
7133 extern qboolean r_shadow_usingdeferredprepass;
7134 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7135 {
7136         qboolean shadowmapping = false;
7137
7138         if (r_timereport_active)
7139                 R_TimeReport("beginscene");
7140
7141         r_refdef.stats[r_stat_renders]++;
7142
7143         R_UpdateFog();
7144
7145         // don't let sound skip if going slow
7146         if (r_refdef.scene.extraupdate)
7147                 S_ExtraUpdate ();
7148
7149         R_MeshQueue_BeginScene();
7150
7151         R_SkyStartFrame();
7152
7153         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);
7154
7155         if (r_timereport_active)
7156                 R_TimeReport("skystartframe");
7157
7158         if (cl.csqc_vidvars.drawworld)
7159         {
7160                 // don't let sound skip if going slow
7161                 if (r_refdef.scene.extraupdate)
7162                         S_ExtraUpdate ();
7163
7164                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7165                 {
7166                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7167                         if (r_timereport_active)
7168                                 R_TimeReport("worldsky");
7169                 }
7170
7171                 if (R_DrawBrushModelsSky() && r_timereport_active)
7172                         R_TimeReport("bmodelsky");
7173
7174                 if (skyrendermasked && skyrenderlater)
7175                 {
7176                         // we have to force off the water clipping plane while rendering sky
7177                         R_SetupView(false, fbo, depthtexture, colortexture);
7178                         R_Sky();
7179                         R_SetupView(true, fbo, depthtexture, colortexture);
7180                         if (r_timereport_active)
7181                                 R_TimeReport("sky");
7182                 }
7183         }
7184
7185         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7186         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7187                 R_Shadow_PrepareModelShadows();
7188         if (r_timereport_active)
7189                 R_TimeReport("preparelights");
7190
7191         if (R_Shadow_ShadowMappingEnabled())
7192                 shadowmapping = true;
7193
7194         if (r_shadow_usingdeferredprepass)
7195                 R_Shadow_DrawPrepass();
7196
7197         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7198         {
7199                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7200                 if (r_timereport_active)
7201                         R_TimeReport("worlddepth");
7202         }
7203         if (r_depthfirst.integer >= 2)
7204         {
7205                 R_DrawModelsDepth();
7206                 if (r_timereport_active)
7207                         R_TimeReport("modeldepth");
7208         }
7209
7210         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7211         {
7212                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7213                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7214                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7215                 // don't let sound skip if going slow
7216                 if (r_refdef.scene.extraupdate)
7217                         S_ExtraUpdate ();
7218         }
7219
7220         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7221         {
7222                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7223                 if (r_timereport_active)
7224                         R_TimeReport("world");
7225         }
7226
7227         // don't let sound skip if going slow
7228         if (r_refdef.scene.extraupdate)
7229                 S_ExtraUpdate ();
7230
7231         R_DrawModels();
7232         if (r_timereport_active)
7233                 R_TimeReport("models");
7234
7235         // don't let sound skip if going slow
7236         if (r_refdef.scene.extraupdate)
7237                 S_ExtraUpdate ();
7238
7239         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7240         {
7241                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7242                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7243                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7244                 // don't let sound skip if going slow
7245                 if (r_refdef.scene.extraupdate)
7246                         S_ExtraUpdate ();
7247         }
7248
7249         if (!r_shadow_usingdeferredprepass)
7250         {
7251                 R_Shadow_DrawLights();
7252                 if (r_timereport_active)
7253                         R_TimeReport("rtlights");
7254         }
7255
7256         // don't let sound skip if going slow
7257         if (r_refdef.scene.extraupdate)
7258                 S_ExtraUpdate ();
7259
7260         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7261         {
7262                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7263                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7264                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7265                 // don't let sound skip if going slow
7266                 if (r_refdef.scene.extraupdate)
7267                         S_ExtraUpdate ();
7268         }
7269
7270         if (cl.csqc_vidvars.drawworld)
7271         {
7272                 if (cl_decals_newsystem.integer)
7273                 {
7274                         R_DrawModelDecals();
7275                         if (r_timereport_active)
7276                                 R_TimeReport("modeldecals");
7277                 }
7278                 else
7279                 {
7280                         R_DrawDecals();
7281                         if (r_timereport_active)
7282                                 R_TimeReport("decals");
7283                 }
7284
7285                 R_DrawParticles();
7286                 if (r_timereport_active)
7287                         R_TimeReport("particles");
7288
7289                 R_DrawExplosions();
7290                 if (r_timereport_active)
7291                         R_TimeReport("explosions");
7292
7293                 R_DrawLightningBeams();
7294                 if (r_timereport_active)
7295                         R_TimeReport("lightning");
7296         }
7297
7298         if (cl.csqc_loaded)
7299                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7300
7301         if (r_refdef.view.showdebug)
7302         {
7303                 if (cl_locs_show.integer)
7304                 {
7305                         R_DrawLocs();
7306                         if (r_timereport_active)
7307                                 R_TimeReport("showlocs");
7308                 }
7309
7310                 if (r_drawportals.integer)
7311                 {
7312                         R_DrawPortals();
7313                         if (r_timereport_active)
7314                                 R_TimeReport("portals");
7315                 }
7316
7317                 if (r_showbboxes.value > 0)
7318                 {
7319                         R_DrawEntityBBoxes();
7320                         if (r_timereport_active)
7321                                 R_TimeReport("bboxes");
7322                 }
7323         }
7324
7325         if (r_transparent.integer)
7326         {
7327                 R_MeshQueue_RenderTransparent();
7328                 if (r_timereport_active)
7329                         R_TimeReport("drawtrans");
7330         }
7331
7332         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))
7333         {
7334                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7335                 if (r_timereport_active)
7336                         R_TimeReport("worlddebug");
7337                 R_DrawModelsDebug();
7338                 if (r_timereport_active)
7339                         R_TimeReport("modeldebug");
7340         }
7341
7342         if (cl.csqc_vidvars.drawworld)
7343         {
7344                 R_Shadow_DrawCoronas();
7345                 if (r_timereport_active)
7346                         R_TimeReport("coronas");
7347         }
7348
7349 #if 0
7350         {
7351                 GL_DepthTest(false);
7352                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7353                 GL_Color(1, 1, 1, 1);
7354                 qglBegin(GL_POLYGON);
7355                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7356                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7357                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7358                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7359                 qglEnd();
7360                 qglBegin(GL_POLYGON);
7361                 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]);
7362                 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]);
7363                 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]);
7364                 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]);
7365                 qglEnd();
7366                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7367         }
7368 #endif
7369
7370         // don't let sound skip if going slow
7371         if (r_refdef.scene.extraupdate)
7372                 S_ExtraUpdate ();
7373 }
7374
7375 static const unsigned short bboxelements[36] =
7376 {
7377         5, 1, 3, 5, 3, 7,
7378         6, 2, 0, 6, 0, 4,
7379         7, 3, 2, 7, 2, 6,
7380         4, 0, 1, 4, 1, 5,
7381         4, 5, 7, 4, 7, 6,
7382         1, 0, 2, 1, 2, 3,
7383 };
7384
7385 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7386 {
7387         int i;
7388         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7389
7390         RSurf_ActiveWorldEntity();
7391
7392         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7393         GL_DepthMask(false);
7394         GL_DepthRange(0, 1);
7395         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7396 //      R_Mesh_ResetTextureState();
7397
7398         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7399         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7400         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7401         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7402         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7403         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7404         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7405         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7406         R_FillColors(color4f, 8, cr, cg, cb, ca);
7407         if (r_refdef.fogenabled)
7408         {
7409                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7410                 {
7411                         f1 = RSurf_FogVertex(v);
7412                         f2 = 1 - f1;
7413                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7414                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7415                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7416                 }
7417         }
7418         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7419         R_Mesh_ResetTextureState();
7420         R_SetupShader_Generic_NoTexture(false, false);
7421         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7422 }
7423
7424 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7425 {
7426         prvm_prog_t *prog = SVVM_prog;
7427         int i;
7428         float color[4];
7429         prvm_edict_t *edict;
7430
7431         // this function draws bounding boxes of server entities
7432         if (!sv.active)
7433                 return;
7434
7435         GL_CullFace(GL_NONE);
7436         R_SetupShader_Generic_NoTexture(false, false);
7437
7438         for (i = 0;i < numsurfaces;i++)
7439         {
7440                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7441                 switch ((int)PRVM_serveredictfloat(edict, solid))
7442                 {
7443                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7444                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7445                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7446                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7447                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7448                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7449                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7450                 }
7451                 color[3] *= r_showbboxes.value;
7452                 color[3] = bound(0, color[3], 1);
7453                 GL_DepthTest(!r_showdisabledepthtest.integer);
7454                 GL_CullFace(r_refdef.view.cullface_front);
7455                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7456         }
7457 }
7458
7459 static void R_DrawEntityBBoxes(void)
7460 {
7461         int i;
7462         prvm_edict_t *edict;
7463         vec3_t center;
7464         prvm_prog_t *prog = SVVM_prog;
7465
7466         // this function draws bounding boxes of server entities
7467         if (!sv.active)
7468                 return;
7469
7470         for (i = 0;i < prog->num_edicts;i++)
7471         {
7472                 edict = PRVM_EDICT_NUM(i);
7473                 if (edict->priv.server->free)
7474                         continue;
7475                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7476                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7477                         continue;
7478                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7479                         continue;
7480                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7481                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7482         }
7483 }
7484
7485 static const int nomodelelement3i[24] =
7486 {
7487         5, 2, 0,
7488         5, 1, 2,
7489         5, 0, 3,
7490         5, 3, 1,
7491         0, 2, 4,
7492         2, 1, 4,
7493         3, 0, 4,
7494         1, 3, 4
7495 };
7496
7497 static const unsigned short nomodelelement3s[24] =
7498 {
7499         5, 2, 0,
7500         5, 1, 2,
7501         5, 0, 3,
7502         5, 3, 1,
7503         0, 2, 4,
7504         2, 1, 4,
7505         3, 0, 4,
7506         1, 3, 4
7507 };
7508
7509 static const float nomodelvertex3f[6*3] =
7510 {
7511         -16,   0,   0,
7512          16,   0,   0,
7513           0, -16,   0,
7514           0,  16,   0,
7515           0,   0, -16,
7516           0,   0,  16
7517 };
7518
7519 static const float nomodelcolor4f[6*4] =
7520 {
7521         0.0f, 0.0f, 0.5f, 1.0f,
7522         0.0f, 0.0f, 0.5f, 1.0f,
7523         0.0f, 0.5f, 0.0f, 1.0f,
7524         0.0f, 0.5f, 0.0f, 1.0f,
7525         0.5f, 0.0f, 0.0f, 1.0f,
7526         0.5f, 0.0f, 0.0f, 1.0f
7527 };
7528
7529 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7530 {
7531         int i;
7532         float f1, f2, *c;
7533         float color4f[6*4];
7534
7535         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);
7536
7537         // this is only called once per entity so numsurfaces is always 1, and
7538         // surfacelist is always {0}, so this code does not handle batches
7539
7540         if (rsurface.ent_flags & RENDER_ADDITIVE)
7541         {
7542                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7543                 GL_DepthMask(false);
7544         }
7545         else if (rsurface.colormod[3] < 1)
7546         {
7547                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7548                 GL_DepthMask(false);
7549         }
7550         else
7551         {
7552                 GL_BlendFunc(GL_ONE, GL_ZERO);
7553                 GL_DepthMask(true);
7554         }
7555         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7556         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7557         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7558         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7559         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7560         for (i = 0, c = color4f;i < 6;i++, c += 4)
7561         {
7562                 c[0] *= rsurface.colormod[0];
7563                 c[1] *= rsurface.colormod[1];
7564                 c[2] *= rsurface.colormod[2];
7565                 c[3] *= rsurface.colormod[3];
7566         }
7567         if (r_refdef.fogenabled)
7568         {
7569                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7570                 {
7571                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7572                         f2 = 1 - f1;
7573                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7574                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7575                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7576                 }
7577         }
7578 //      R_Mesh_ResetTextureState();
7579         R_SetupShader_Generic_NoTexture(false, false);
7580         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7581         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7582 }
7583
7584 void R_DrawNoModel(entity_render_t *ent)
7585 {
7586         vec3_t org;
7587         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7588         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7589                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7590         else
7591                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7592 }
7593
7594 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7595 {
7596         vec3_t right1, right2, diff, normal;
7597
7598         VectorSubtract (org2, org1, normal);
7599
7600         // calculate 'right' vector for start
7601         VectorSubtract (r_refdef.view.origin, org1, diff);
7602         CrossProduct (normal, diff, right1);
7603         VectorNormalize (right1);
7604
7605         // calculate 'right' vector for end
7606         VectorSubtract (r_refdef.view.origin, org2, diff);
7607         CrossProduct (normal, diff, right2);
7608         VectorNormalize (right2);
7609
7610         vert[ 0] = org1[0] + width * right1[0];
7611         vert[ 1] = org1[1] + width * right1[1];
7612         vert[ 2] = org1[2] + width * right1[2];
7613         vert[ 3] = org1[0] - width * right1[0];
7614         vert[ 4] = org1[1] - width * right1[1];
7615         vert[ 5] = org1[2] - width * right1[2];
7616         vert[ 6] = org2[0] - width * right2[0];
7617         vert[ 7] = org2[1] - width * right2[1];
7618         vert[ 8] = org2[2] - width * right2[2];
7619         vert[ 9] = org2[0] + width * right2[0];
7620         vert[10] = org2[1] + width * right2[1];
7621         vert[11] = org2[2] + width * right2[2];
7622 }
7623
7624 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)
7625 {
7626         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7627         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7628         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7629         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7630         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7631         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7632         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7633         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7634         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7635         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7636         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7637         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7638 }
7639
7640 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7641 {
7642         int i;
7643         float *vertex3f;
7644         float v[3];
7645         VectorSet(v, x, y, z);
7646         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7647                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7648                         break;
7649         if (i == mesh->numvertices)
7650         {
7651                 if (mesh->numvertices < mesh->maxvertices)
7652                 {
7653                         VectorCopy(v, vertex3f);
7654                         mesh->numvertices++;
7655                 }
7656                 return mesh->numvertices;
7657         }
7658         else
7659                 return i;
7660 }
7661
7662 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7663 {
7664         int i;
7665         int *e, element[3];
7666         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7667         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7668         e = mesh->element3i + mesh->numtriangles * 3;
7669         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7670         {
7671                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7672                 if (mesh->numtriangles < mesh->maxtriangles)
7673                 {
7674                         *e++ = element[0];
7675                         *e++ = element[1];
7676                         *e++ = element[2];
7677                         mesh->numtriangles++;
7678                 }
7679                 element[1] = element[2];
7680         }
7681 }
7682
7683 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7684 {
7685         int i;
7686         int *e, element[3];
7687         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7688         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7689         e = mesh->element3i + mesh->numtriangles * 3;
7690         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7691         {
7692                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7693                 if (mesh->numtriangles < mesh->maxtriangles)
7694                 {
7695                         *e++ = element[0];
7696                         *e++ = element[1];
7697                         *e++ = element[2];
7698                         mesh->numtriangles++;
7699                 }
7700                 element[1] = element[2];
7701         }
7702 }
7703
7704 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7705 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7706 {
7707         int planenum, planenum2;
7708         int w;
7709         int tempnumpoints;
7710         mplane_t *plane, *plane2;
7711         double maxdist;
7712         double temppoints[2][256*3];
7713         // figure out how large a bounding box we need to properly compute this brush
7714         maxdist = 0;
7715         for (w = 0;w < numplanes;w++)
7716                 maxdist = max(maxdist, fabs(planes[w].dist));
7717         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7718         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7719         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7720         {
7721                 w = 0;
7722                 tempnumpoints = 4;
7723                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7724                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7725                 {
7726                         if (planenum2 == planenum)
7727                                 continue;
7728                         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);
7729                         w = !w;
7730                 }
7731                 if (tempnumpoints < 3)
7732                         continue;
7733                 // generate elements forming a triangle fan for this polygon
7734                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7735         }
7736 }
7737
7738 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)
7739 {
7740         texturelayer_t *layer;
7741         layer = t->currentlayers + t->currentnumlayers++;
7742         layer->type = type;
7743         layer->depthmask = depthmask;
7744         layer->blendfunc1 = blendfunc1;
7745         layer->blendfunc2 = blendfunc2;
7746         layer->texture = texture;
7747         layer->texmatrix = *matrix;
7748         layer->color[0] = r;
7749         layer->color[1] = g;
7750         layer->color[2] = b;
7751         layer->color[3] = a;
7752 }
7753
7754 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7755 {
7756         if(parms[0] == 0 && parms[1] == 0)
7757                 return false;
7758         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7759                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7760                         return false;
7761         return true;
7762 }
7763
7764 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7765 {
7766         double index, f;
7767         index = parms[2] + rsurface.shadertime * parms[3];
7768         index -= floor(index);
7769         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7770         {
7771         default:
7772         case Q3WAVEFUNC_NONE:
7773         case Q3WAVEFUNC_NOISE:
7774         case Q3WAVEFUNC_COUNT:
7775                 f = 0;
7776                 break;
7777         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7778         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7779         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7780         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7781         case Q3WAVEFUNC_TRIANGLE:
7782                 index *= 4;
7783                 f = index - floor(index);
7784                 if (index < 1)
7785                 {
7786                         // f = f;
7787                 }
7788                 else if (index < 2)
7789                         f = 1 - f;
7790                 else if (index < 3)
7791                         f = -f;
7792                 else
7793                         f = -(1 - f);
7794                 break;
7795         }
7796         f = parms[0] + parms[1] * f;
7797         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7798                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7799         return (float) f;
7800 }
7801
7802 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7803 {
7804         int w, h, idx;
7805         double f;
7806         double offsetd[2];
7807         float tcmat[12];
7808         matrix4x4_t matrix, temp;
7809         switch(tcmod->tcmod)
7810         {
7811                 case Q3TCMOD_COUNT:
7812                 case Q3TCMOD_NONE:
7813                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7814                                 matrix = r_waterscrollmatrix;
7815                         else
7816                                 matrix = identitymatrix;
7817                         break;
7818                 case Q3TCMOD_ENTITYTRANSLATE:
7819                         // this is used in Q3 to allow the gamecode to control texcoord
7820                         // scrolling on the entity, which is not supported in darkplaces yet.
7821                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7822                         break;
7823                 case Q3TCMOD_ROTATE:
7824                         f = tcmod->parms[0] * rsurface.shadertime;
7825                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7826                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7827                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7828                         break;
7829                 case Q3TCMOD_SCALE:
7830                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7831                         break;
7832                 case Q3TCMOD_SCROLL:
7833                         // extra care is needed because of precision breakdown with large values of time
7834                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7835                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7836                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7837                         break;
7838                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7839                         w = (int) tcmod->parms[0];
7840                         h = (int) tcmod->parms[1];
7841                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7842                         f = f - floor(f);
7843                         idx = (int) floor(f * w * h);
7844                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7845                         break;
7846                 case Q3TCMOD_STRETCH:
7847                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7848                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7849                         break;
7850                 case Q3TCMOD_TRANSFORM:
7851                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7852                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7853                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7854                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7855                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7856                         break;
7857                 case Q3TCMOD_TURBULENT:
7858                         // this is handled in the RSurf_PrepareVertices function
7859                         matrix = identitymatrix;
7860                         break;
7861         }
7862         temp = *texmatrix;
7863         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7864 }
7865
7866 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7867 {
7868         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7869         char name[MAX_QPATH];
7870         skinframe_t *skinframe;
7871         unsigned char pixels[296*194];
7872         strlcpy(cache->name, skinname, sizeof(cache->name));
7873         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7874         if (developer_loading.integer)
7875                 Con_Printf("loading %s\n", name);
7876         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7877         if (!skinframe || !skinframe->base)
7878         {
7879                 unsigned char *f;
7880                 fs_offset_t filesize;
7881                 skinframe = NULL;
7882                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7883                 if (f)
7884                 {
7885                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7886                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7887                         Mem_Free(f);
7888                 }
7889         }
7890         cache->skinframe = skinframe;
7891 }
7892
7893 texture_t *R_GetCurrentTexture(texture_t *t)
7894 {
7895         int i;
7896         const entity_render_t *ent = rsurface.entity;
7897         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7898         q3shaderinfo_layer_tcmod_t *tcmod;
7899
7900         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7901                 return t->currentframe;
7902         t->update_lastrenderframe = r_textureframe;
7903         t->update_lastrenderentity = (void *)ent;
7904
7905         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7906                 t->camera_entity = ent->entitynumber;
7907         else
7908                 t->camera_entity = 0;
7909
7910         // switch to an alternate material if this is a q1bsp animated material
7911         {
7912                 texture_t *texture = t;
7913                 int s = rsurface.ent_skinnum;
7914                 if ((unsigned int)s >= (unsigned int)model->numskins)
7915                         s = 0;
7916                 if (model->skinscenes)
7917                 {
7918                         if (model->skinscenes[s].framecount > 1)
7919                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7920                         else
7921                                 s = model->skinscenes[s].firstframe;
7922                 }
7923                 if (s > 0)
7924                         t = t + s * model->num_surfaces;
7925                 if (t->animated)
7926                 {
7927                         // use an alternate animation if the entity's frame is not 0,
7928                         // and only if the texture has an alternate animation
7929                         if (rsurface.ent_alttextures && t->anim_total[1])
7930                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7931                         else
7932                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7933                 }
7934                 texture->currentframe = t;
7935         }
7936
7937         // update currentskinframe to be a qw skin or animation frame
7938         if (rsurface.ent_qwskin >= 0)
7939         {
7940                 i = rsurface.ent_qwskin;
7941                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7942                 {
7943                         r_qwskincache_size = cl.maxclients;
7944                         if (r_qwskincache)
7945                                 Mem_Free(r_qwskincache);
7946                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7947                 }
7948                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7949                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7950                 t->currentskinframe = r_qwskincache[i].skinframe;
7951                 if (t->currentskinframe == NULL)
7952                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7953         }
7954         else if (t->numskinframes >= 2)
7955                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7956         if (t->backgroundnumskinframes >= 2)
7957                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7958
7959         t->currentmaterialflags = t->basematerialflags;
7960         t->currentalpha = rsurface.colormod[3];
7961         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7962                 t->currentalpha *= r_wateralpha.value;
7963         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7964                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7965         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7966                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7967         if (!(rsurface.ent_flags & RENDER_LIGHT))
7968                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7969         else if (FAKELIGHT_ENABLED)
7970         {
7971                 // no modellight if using fakelight for the map
7972         }
7973         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7974         {
7975                 // pick a model lighting mode
7976                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7977                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7978                 else
7979                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7980         }
7981         if (rsurface.ent_flags & RENDER_ADDITIVE)
7982                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7983         else if (t->currentalpha < 1)
7984                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7985         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7986         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7987                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7988         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7989                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7990         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7991                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7992         if (t->backgroundnumskinframes)
7993                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7994         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7995         {
7996                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7997                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7998         }
7999         else
8000                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8001         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8002         {
8003                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8004                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8005         }
8006         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8007                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8008
8009         // there is no tcmod
8010         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8011         {
8012                 t->currenttexmatrix = r_waterscrollmatrix;
8013                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8014         }
8015         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8016         {
8017                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8018                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8019         }
8020
8021         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8022                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8023         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8024                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8025
8026         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8027         if (t->currentskinframe->qpixels)
8028                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8029         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8030         if (!t->basetexture)
8031                 t->basetexture = r_texture_notexture;
8032         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8033         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8034         t->nmaptexture = t->currentskinframe->nmap;
8035         if (!t->nmaptexture)
8036                 t->nmaptexture = r_texture_blanknormalmap;
8037         t->glosstexture = r_texture_black;
8038         t->glowtexture = t->currentskinframe->glow;
8039         t->fogtexture = t->currentskinframe->fog;
8040         t->reflectmasktexture = t->currentskinframe->reflect;
8041         if (t->backgroundnumskinframes)
8042         {
8043                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8044                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8045                 t->backgroundglosstexture = r_texture_black;
8046                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8047                 if (!t->backgroundnmaptexture)
8048                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8049                 // make sure that if glow is going to be used, both textures are not NULL
8050                 if (!t->backgroundglowtexture && t->glowtexture)
8051                         t->backgroundglowtexture = r_texture_black;
8052                 if (!t->glowtexture && t->backgroundglowtexture)
8053                         t->glowtexture = r_texture_black;
8054         }
8055         else
8056         {
8057                 t->backgroundbasetexture = r_texture_white;
8058                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8059                 t->backgroundglosstexture = r_texture_black;
8060                 t->backgroundglowtexture = NULL;
8061         }
8062         t->specularpower = r_shadow_glossexponent.value;
8063         // TODO: store reference values for these in the texture?
8064         t->specularscale = 0;
8065         if (r_shadow_gloss.integer > 0)
8066         {
8067                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8068                 {
8069                         if (r_shadow_glossintensity.value > 0)
8070                         {
8071                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8072                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8073                                 t->specularscale = r_shadow_glossintensity.value;
8074                         }
8075                 }
8076                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8077                 {
8078                         t->glosstexture = r_texture_white;
8079                         t->backgroundglosstexture = r_texture_white;
8080                         t->specularscale = r_shadow_gloss2intensity.value;
8081                         t->specularpower = r_shadow_gloss2exponent.value;
8082                 }
8083         }
8084         t->specularscale *= t->specularscalemod;
8085         t->specularpower *= t->specularpowermod;
8086         t->rtlightambient = 0;
8087
8088         // lightmaps mode looks bad with dlights using actual texturing, so turn
8089         // off the colormap and glossmap, but leave the normalmap on as it still
8090         // accurately represents the shading involved
8091         if (gl_lightmaps.integer)
8092         {
8093                 t->basetexture = r_texture_grey128;
8094                 t->pantstexture = r_texture_black;
8095                 t->shirttexture = r_texture_black;
8096                 if (gl_lightmaps.integer < 2)
8097                         t->nmaptexture = r_texture_blanknormalmap;
8098                 t->glosstexture = r_texture_black;
8099                 t->glowtexture = NULL;
8100                 t->fogtexture = NULL;
8101                 t->reflectmasktexture = NULL;
8102                 t->backgroundbasetexture = NULL;
8103                 if (gl_lightmaps.integer < 2)
8104                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8105                 t->backgroundglosstexture = r_texture_black;
8106                 t->backgroundglowtexture = NULL;
8107                 t->specularscale = 0;
8108                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8109         }
8110
8111         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8112         VectorClear(t->dlightcolor);
8113         t->currentnumlayers = 0;
8114         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8115         {
8116                 int blendfunc1, blendfunc2;
8117                 qboolean depthmask;
8118                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8119                 {
8120                         blendfunc1 = GL_SRC_ALPHA;
8121                         blendfunc2 = GL_ONE;
8122                 }
8123                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8124                 {
8125                         blendfunc1 = GL_SRC_ALPHA;
8126                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8127                 }
8128                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8129                 {
8130                         blendfunc1 = t->customblendfunc[0];
8131                         blendfunc2 = t->customblendfunc[1];
8132                 }
8133                 else
8134                 {
8135                         blendfunc1 = GL_ONE;
8136                         blendfunc2 = GL_ZERO;
8137                 }
8138                 // don't colormod evilblend textures
8139                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8140                         VectorSet(t->lightmapcolor, 1, 1, 1);
8141                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8142                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8143                 {
8144                         // fullbright is not affected by r_refdef.lightmapintensity
8145                         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]);
8146                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8147                                 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]);
8148                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8149                                 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]);
8150                 }
8151                 else
8152                 {
8153                         vec3_t ambientcolor;
8154                         float colorscale;
8155                         // set the color tint used for lights affecting this surface
8156                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8157                         colorscale = 2;
8158                         // q3bsp has no lightmap updates, so the lightstylevalue that
8159                         // would normally be baked into the lightmap must be
8160                         // applied to the color
8161                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8162                         if (model->type == mod_brushq3)
8163                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8164                         colorscale *= r_refdef.lightmapintensity;
8165                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8166                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8167                         // basic lit geometry
8168                         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]);
8169                         // add pants/shirt if needed
8170                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8171                                 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]);
8172                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8173                                 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]);
8174                         // now add ambient passes if needed
8175                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8176                         {
8177                                 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]);
8178                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8179                                         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]);
8180                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8181                                         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]);
8182                         }
8183                 }
8184                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8185                         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]);
8186                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8187                 {
8188                         // if this is opaque use alpha blend which will darken the earlier
8189                         // passes cheaply.
8190                         //
8191                         // if this is an alpha blended material, all the earlier passes
8192                         // were darkened by fog already, so we only need to add the fog
8193                         // color ontop through the fog mask texture
8194                         //
8195                         // if this is an additive blended material, all the earlier passes
8196                         // were darkened by fog already, and we should not add fog color
8197                         // (because the background was not darkened, there is no fog color
8198                         // that was lost behind it).
8199                         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]);
8200                 }
8201         }
8202
8203         return t->currentframe;
8204 }
8205
8206 rsurfacestate_t rsurface;
8207
8208 void RSurf_ActiveWorldEntity(void)
8209 {
8210         dp_model_t *model = r_refdef.scene.worldmodel;
8211         //if (rsurface.entity == r_refdef.scene.worldentity)
8212         //      return;
8213         rsurface.entity = r_refdef.scene.worldentity;
8214         rsurface.skeleton = NULL;
8215         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8216         rsurface.ent_skinnum = 0;
8217         rsurface.ent_qwskin = -1;
8218         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8219         rsurface.shadertime = r_refdef.scene.time;
8220         rsurface.matrix = identitymatrix;
8221         rsurface.inversematrix = identitymatrix;
8222         rsurface.matrixscale = 1;
8223         rsurface.inversematrixscale = 1;
8224         R_EntityMatrix(&identitymatrix);
8225         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8226         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8227         rsurface.fograngerecip = r_refdef.fograngerecip;
8228         rsurface.fogheightfade = r_refdef.fogheightfade;
8229         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8230         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8231         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8232         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8233         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8234         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8235         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8236         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8237         rsurface.colormod[3] = 1;
8238         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);
8239         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8240         rsurface.frameblend[0].lerp = 1;
8241         rsurface.ent_alttextures = false;
8242         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8243         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8244         rsurface.entityskeletaltransform3x4 = NULL;
8245         rsurface.entityskeletalnumtransforms = 0;
8246         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8247         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8248         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8249         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8250         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8251         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8252         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8253         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8254         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8255         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8256         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8257         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8258         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8259         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8260         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8261         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8262         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8263         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8264         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8265         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8266         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8267         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8268         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8269         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8270         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8271         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8272         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8273         rsurface.modelelement3i = model->surfmesh.data_element3i;
8274         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8275         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8276         rsurface.modelelement3s = model->surfmesh.data_element3s;
8277         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8278         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8279         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8280         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8281         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8282         rsurface.modelsurfaces = model->data_surfaces;
8283         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8284         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8285         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8286         rsurface.modelgeneratedvertex = false;
8287         rsurface.batchgeneratedvertex = false;
8288         rsurface.batchfirstvertex = 0;
8289         rsurface.batchnumvertices = 0;
8290         rsurface.batchfirsttriangle = 0;
8291         rsurface.batchnumtriangles = 0;
8292         rsurface.batchvertex3f  = NULL;
8293         rsurface.batchvertex3f_vertexbuffer = NULL;
8294         rsurface.batchvertex3f_bufferoffset = 0;
8295         rsurface.batchsvector3f = NULL;
8296         rsurface.batchsvector3f_vertexbuffer = NULL;
8297         rsurface.batchsvector3f_bufferoffset = 0;
8298         rsurface.batchtvector3f = NULL;
8299         rsurface.batchtvector3f_vertexbuffer = NULL;
8300         rsurface.batchtvector3f_bufferoffset = 0;
8301         rsurface.batchnormal3f  = NULL;
8302         rsurface.batchnormal3f_vertexbuffer = NULL;
8303         rsurface.batchnormal3f_bufferoffset = 0;
8304         rsurface.batchlightmapcolor4f = NULL;
8305         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8306         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8307         rsurface.batchtexcoordtexture2f = NULL;
8308         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8309         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8310         rsurface.batchtexcoordlightmap2f = NULL;
8311         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8312         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8313         rsurface.batchskeletalindex4ub = NULL;
8314         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8315         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8316         rsurface.batchskeletalweight4ub = NULL;
8317         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8318         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8319         rsurface.batchvertexmesh = NULL;
8320         rsurface.batchvertexmeshbuffer = NULL;
8321         rsurface.batchvertex3fbuffer = NULL;
8322         rsurface.batchelement3i = NULL;
8323         rsurface.batchelement3i_indexbuffer = NULL;
8324         rsurface.batchelement3i_bufferoffset = 0;
8325         rsurface.batchelement3s = NULL;
8326         rsurface.batchelement3s_indexbuffer = NULL;
8327         rsurface.batchelement3s_bufferoffset = 0;
8328         rsurface.passcolor4f = NULL;
8329         rsurface.passcolor4f_vertexbuffer = NULL;
8330         rsurface.passcolor4f_bufferoffset = 0;
8331         rsurface.forcecurrenttextureupdate = false;
8332 }
8333
8334 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8335 {
8336         dp_model_t *model = ent->model;
8337         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8338         //      return;
8339         rsurface.entity = (entity_render_t *)ent;
8340         rsurface.skeleton = ent->skeleton;
8341         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8342         rsurface.ent_skinnum = ent->skinnum;
8343         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;
8344         rsurface.ent_flags = ent->flags;
8345         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8346         rsurface.matrix = ent->matrix;
8347         rsurface.inversematrix = ent->inversematrix;
8348         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8349         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8350         R_EntityMatrix(&rsurface.matrix);
8351         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8352         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8353         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8354         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8355         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8356         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8357         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8358         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8359         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8360         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8361         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8362         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8363         rsurface.colormod[3] = ent->alpha;
8364         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8365         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8366         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8367         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8368         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8369         if (ent->model->brush.submodel && !prepass)
8370         {
8371                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8372                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8373         }
8374         // if the animcache code decided it should use the shader path, skip the deform step
8375         rsurface.entityskeletaltransform3x4 = ent->animcache_vertex3f ? NULL : ent->animcache_skeletaltransform3x4;
8376         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8377         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8378         {
8379                 if (ent->animcache_vertex3f)
8380                 {
8381                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8382                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8383                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8384                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8385                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8386                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8387                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8388                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8389                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8390                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8391                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8392                 }
8393                 else if (wanttangents)
8394                 {
8395                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8396                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8397                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8398                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8399                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8400                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8401                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8402                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8403                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8404                         rsurface.modelvertexmesh = NULL;
8405                         rsurface.modelvertexmeshbuffer = NULL;
8406                         rsurface.modelvertex3fbuffer = NULL;
8407                 }
8408                 else if (wantnormals)
8409                 {
8410                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8411                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8412                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8413                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8414                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8415                         rsurface.modelsvector3f = NULL;
8416                         rsurface.modeltvector3f = NULL;
8417                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8418                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8419                         rsurface.modelvertexmesh = NULL;
8420                         rsurface.modelvertexmeshbuffer = NULL;
8421                         rsurface.modelvertex3fbuffer = NULL;
8422                 }
8423                 else
8424                 {
8425                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8426                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8427                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8428                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8429                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8430                         rsurface.modelsvector3f = NULL;
8431                         rsurface.modeltvector3f = NULL;
8432                         rsurface.modelnormal3f = NULL;
8433                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8434                         rsurface.modelvertexmesh = NULL;
8435                         rsurface.modelvertexmeshbuffer = NULL;
8436                         rsurface.modelvertex3fbuffer = NULL;
8437                 }
8438                 rsurface.modelvertex3f_vertexbuffer = 0;
8439                 rsurface.modelvertex3f_bufferoffset = 0;
8440                 rsurface.modelsvector3f_vertexbuffer = 0;
8441                 rsurface.modelsvector3f_bufferoffset = 0;
8442                 rsurface.modeltvector3f_vertexbuffer = 0;
8443                 rsurface.modeltvector3f_bufferoffset = 0;
8444                 rsurface.modelnormal3f_vertexbuffer = 0;
8445                 rsurface.modelnormal3f_bufferoffset = 0;
8446                 rsurface.modelgeneratedvertex = true;
8447         }
8448         else
8449         {
8450                 if (rsurface.entityskeletaltransform3x4)
8451                 {
8452                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8453                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8454                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8455                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8456                 }
8457                 else
8458                 {
8459                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8460                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8461                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8462                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8463                 }
8464                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8465                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8466                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8467                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8468                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8469                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8470                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8471                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8472                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8473                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8474                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8475                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8476                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8477                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8478                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8479                 rsurface.modelgeneratedvertex = false;
8480         }
8481         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8482         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8483         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8484         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8485         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8486         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8487         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8488         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8489         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8490         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8491         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8492         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8493         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8494         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8495         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8496         rsurface.modelelement3i = model->surfmesh.data_element3i;
8497         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8498         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8499         rsurface.modelelement3s = model->surfmesh.data_element3s;
8500         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8501         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8502         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8503         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8504         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8505         rsurface.modelsurfaces = model->data_surfaces;
8506         rsurface.batchgeneratedvertex = false;
8507         rsurface.batchfirstvertex = 0;
8508         rsurface.batchnumvertices = 0;
8509         rsurface.batchfirsttriangle = 0;
8510         rsurface.batchnumtriangles = 0;
8511         rsurface.batchvertex3f  = NULL;
8512         rsurface.batchvertex3f_vertexbuffer = NULL;
8513         rsurface.batchvertex3f_bufferoffset = 0;
8514         rsurface.batchsvector3f = NULL;
8515         rsurface.batchsvector3f_vertexbuffer = NULL;
8516         rsurface.batchsvector3f_bufferoffset = 0;
8517         rsurface.batchtvector3f = NULL;
8518         rsurface.batchtvector3f_vertexbuffer = NULL;
8519         rsurface.batchtvector3f_bufferoffset = 0;
8520         rsurface.batchnormal3f  = NULL;
8521         rsurface.batchnormal3f_vertexbuffer = NULL;
8522         rsurface.batchnormal3f_bufferoffset = 0;
8523         rsurface.batchlightmapcolor4f = NULL;
8524         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8525         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8526         rsurface.batchtexcoordtexture2f = NULL;
8527         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8528         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8529         rsurface.batchtexcoordlightmap2f = NULL;
8530         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8531         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8532         rsurface.batchskeletalindex4ub = NULL;
8533         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8534         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8535         rsurface.batchskeletalweight4ub = NULL;
8536         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8537         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8538         rsurface.batchvertexmesh = NULL;
8539         rsurface.batchvertexmeshbuffer = NULL;
8540         rsurface.batchvertex3fbuffer = NULL;
8541         rsurface.batchelement3i = NULL;
8542         rsurface.batchelement3i_indexbuffer = NULL;
8543         rsurface.batchelement3i_bufferoffset = 0;
8544         rsurface.batchelement3s = NULL;
8545         rsurface.batchelement3s_indexbuffer = NULL;
8546         rsurface.batchelement3s_bufferoffset = 0;
8547         rsurface.passcolor4f = NULL;
8548         rsurface.passcolor4f_vertexbuffer = NULL;
8549         rsurface.passcolor4f_bufferoffset = 0;
8550         rsurface.forcecurrenttextureupdate = false;
8551 }
8552
8553 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)
8554 {
8555         rsurface.entity = r_refdef.scene.worldentity;
8556         rsurface.skeleton = NULL;
8557         rsurface.ent_skinnum = 0;
8558         rsurface.ent_qwskin = -1;
8559         rsurface.ent_flags = entflags;
8560         rsurface.shadertime = r_refdef.scene.time - shadertime;
8561         rsurface.modelnumvertices = numvertices;
8562         rsurface.modelnumtriangles = numtriangles;
8563         rsurface.matrix = *matrix;
8564         rsurface.inversematrix = *inversematrix;
8565         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8566         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8567         R_EntityMatrix(&rsurface.matrix);
8568         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8569         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8570         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8571         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8572         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8573         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8574         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8575         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8576         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8577         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8578         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8579         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8580         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);
8581         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8582         rsurface.frameblend[0].lerp = 1;
8583         rsurface.ent_alttextures = false;
8584         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8585         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8586         rsurface.entityskeletaltransform3x4 = NULL;
8587         rsurface.entityskeletalnumtransforms = 0;
8588         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8589         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8590         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8591         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8592         if (wanttangents)
8593         {
8594                 rsurface.modelvertex3f = (float *)vertex3f;
8595                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8596                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8597                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8598         }
8599         else if (wantnormals)
8600         {
8601                 rsurface.modelvertex3f = (float *)vertex3f;
8602                 rsurface.modelsvector3f = NULL;
8603                 rsurface.modeltvector3f = NULL;
8604                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8605         }
8606         else
8607         {
8608                 rsurface.modelvertex3f = (float *)vertex3f;
8609                 rsurface.modelsvector3f = NULL;
8610                 rsurface.modeltvector3f = NULL;
8611                 rsurface.modelnormal3f = NULL;
8612         }
8613         rsurface.modelvertexmesh = NULL;
8614         rsurface.modelvertexmeshbuffer = NULL;
8615         rsurface.modelvertex3fbuffer = NULL;
8616         rsurface.modelvertex3f_vertexbuffer = 0;
8617         rsurface.modelvertex3f_bufferoffset = 0;
8618         rsurface.modelsvector3f_vertexbuffer = 0;
8619         rsurface.modelsvector3f_bufferoffset = 0;
8620         rsurface.modeltvector3f_vertexbuffer = 0;
8621         rsurface.modeltvector3f_bufferoffset = 0;
8622         rsurface.modelnormal3f_vertexbuffer = 0;
8623         rsurface.modelnormal3f_bufferoffset = 0;
8624         rsurface.modelgeneratedvertex = true;
8625         rsurface.modellightmapcolor4f  = (float *)color4f;
8626         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8627         rsurface.modellightmapcolor4f_bufferoffset = 0;
8628         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8629         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8630         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8631         rsurface.modeltexcoordlightmap2f  = NULL;
8632         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8633         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8634         rsurface.modelskeletalindex4ub = NULL;
8635         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8636         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8637         rsurface.modelskeletalweight4ub = NULL;
8638         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8639         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8640         rsurface.modelelement3i = (int *)element3i;
8641         rsurface.modelelement3i_indexbuffer = NULL;
8642         rsurface.modelelement3i_bufferoffset = 0;
8643         rsurface.modelelement3s = (unsigned short *)element3s;
8644         rsurface.modelelement3s_indexbuffer = NULL;
8645         rsurface.modelelement3s_bufferoffset = 0;
8646         rsurface.modellightmapoffsets = NULL;
8647         rsurface.modelsurfaces = NULL;
8648         rsurface.batchgeneratedvertex = false;
8649         rsurface.batchfirstvertex = 0;
8650         rsurface.batchnumvertices = 0;
8651         rsurface.batchfirsttriangle = 0;
8652         rsurface.batchnumtriangles = 0;
8653         rsurface.batchvertex3f  = NULL;
8654         rsurface.batchvertex3f_vertexbuffer = NULL;
8655         rsurface.batchvertex3f_bufferoffset = 0;
8656         rsurface.batchsvector3f = NULL;
8657         rsurface.batchsvector3f_vertexbuffer = NULL;
8658         rsurface.batchsvector3f_bufferoffset = 0;
8659         rsurface.batchtvector3f = NULL;
8660         rsurface.batchtvector3f_vertexbuffer = NULL;
8661         rsurface.batchtvector3f_bufferoffset = 0;
8662         rsurface.batchnormal3f  = NULL;
8663         rsurface.batchnormal3f_vertexbuffer = NULL;
8664         rsurface.batchnormal3f_bufferoffset = 0;
8665         rsurface.batchlightmapcolor4f = NULL;
8666         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8667         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8668         rsurface.batchtexcoordtexture2f = NULL;
8669         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8670         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8671         rsurface.batchtexcoordlightmap2f = NULL;
8672         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8673         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8674         rsurface.batchskeletalindex4ub = NULL;
8675         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8676         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8677         rsurface.batchskeletalweight4ub = NULL;
8678         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8679         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8680         rsurface.batchvertexmesh = NULL;
8681         rsurface.batchvertexmeshbuffer = NULL;
8682         rsurface.batchvertex3fbuffer = NULL;
8683         rsurface.batchelement3i = NULL;
8684         rsurface.batchelement3i_indexbuffer = NULL;
8685         rsurface.batchelement3i_bufferoffset = 0;
8686         rsurface.batchelement3s = NULL;
8687         rsurface.batchelement3s_indexbuffer = NULL;
8688         rsurface.batchelement3s_bufferoffset = 0;
8689         rsurface.passcolor4f = NULL;
8690         rsurface.passcolor4f_vertexbuffer = NULL;
8691         rsurface.passcolor4f_bufferoffset = 0;
8692         rsurface.forcecurrenttextureupdate = true;
8693
8694         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8695         {
8696                 if ((wantnormals || wanttangents) && !normal3f)
8697                 {
8698                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8699                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8700                 }
8701                 if (wanttangents && !svector3f)
8702                 {
8703                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8704                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8705                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8706                 }
8707         }
8708 }
8709
8710 float RSurf_FogPoint(const float *v)
8711 {
8712         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8713         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8714         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8715         float FogHeightFade = r_refdef.fogheightfade;
8716         float fogfrac;
8717         unsigned int fogmasktableindex;
8718         if (r_refdef.fogplaneviewabove)
8719                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8720         else
8721                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8722         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8723         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8724 }
8725
8726 float RSurf_FogVertex(const float *v)
8727 {
8728         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8729         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8730         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8731         float FogHeightFade = rsurface.fogheightfade;
8732         float fogfrac;
8733         unsigned int fogmasktableindex;
8734         if (r_refdef.fogplaneviewabove)
8735                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8736         else
8737                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8738         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8739         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8740 }
8741
8742 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8743 {
8744         int i;
8745         for (i = 0;i < numelements;i++)
8746                 outelement3i[i] = inelement3i[i] + adjust;
8747 }
8748
8749 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8750 extern cvar_t gl_vbo;
8751 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8752 {
8753         int deformindex;
8754         int firsttriangle;
8755         int numtriangles;
8756         int firstvertex;
8757         int endvertex;
8758         int numvertices;
8759         int surfacefirsttriangle;
8760         int surfacenumtriangles;
8761         int surfacefirstvertex;
8762         int surfaceendvertex;
8763         int surfacenumvertices;
8764         int batchnumsurfaces = texturenumsurfaces;
8765         int batchnumvertices;
8766         int batchnumtriangles;
8767         int needsupdate;
8768         int i, j;
8769         qboolean gaps;
8770         qboolean dynamicvertex;
8771         float amplitude;
8772         float animpos;
8773         float scale;
8774         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8775         float waveparms[4];
8776         unsigned char *ub;
8777         q3shaderinfo_deform_t *deform;
8778         const msurface_t *surface, *firstsurface;
8779         r_vertexmesh_t *vertexmesh;
8780         if (!texturenumsurfaces)
8781                 return;
8782         // find vertex range of this surface batch
8783         gaps = false;
8784         firstsurface = texturesurfacelist[0];
8785         firsttriangle = firstsurface->num_firsttriangle;
8786         batchnumvertices = 0;
8787         batchnumtriangles = 0;
8788         firstvertex = endvertex = firstsurface->num_firstvertex;
8789         for (i = 0;i < texturenumsurfaces;i++)
8790         {
8791                 surface = texturesurfacelist[i];
8792                 if (surface != firstsurface + i)
8793                         gaps = true;
8794                 surfacefirstvertex = surface->num_firstvertex;
8795                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8796                 surfacenumvertices = surface->num_vertices;
8797                 surfacenumtriangles = surface->num_triangles;
8798                 if (firstvertex > surfacefirstvertex)
8799                         firstvertex = surfacefirstvertex;
8800                 if (endvertex < surfaceendvertex)
8801                         endvertex = surfaceendvertex;
8802                 batchnumvertices += surfacenumvertices;
8803                 batchnumtriangles += surfacenumtriangles;
8804         }
8805
8806         r_refdef.stats[r_stat_batch_batches]++;
8807         if (gaps)
8808                 r_refdef.stats[r_stat_batch_withgaps]++;
8809         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8810         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8811         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8812
8813         // we now know the vertex range used, and if there are any gaps in it
8814         rsurface.batchfirstvertex = firstvertex;
8815         rsurface.batchnumvertices = endvertex - firstvertex;
8816         rsurface.batchfirsttriangle = firsttriangle;
8817         rsurface.batchnumtriangles = batchnumtriangles;
8818
8819         // this variable holds flags for which properties have been updated that
8820         // may require regenerating vertexmesh array...
8821         needsupdate = 0;
8822
8823         // check if any dynamic vertex processing must occur
8824         dynamicvertex = false;
8825
8826         // a cvar to force the dynamic vertex path to be taken, for debugging
8827         if (r_batch_debugdynamicvertexpath.integer)
8828         {
8829                 if (!dynamicvertex)
8830                 {
8831                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8832                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8833                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8834                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8835                 }
8836                 dynamicvertex = true;
8837         }
8838
8839         // if there is a chance of animated vertex colors, it's a dynamic batch
8840         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8841         {
8842                 if (!dynamicvertex)
8843                 {
8844                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
8845                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
8846                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
8847                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
8848                 }
8849                 dynamicvertex = true;
8850                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8851         }
8852
8853         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8854         {
8855                 switch (deform->deform)
8856                 {
8857                 default:
8858                 case Q3DEFORM_PROJECTIONSHADOW:
8859                 case Q3DEFORM_TEXT0:
8860                 case Q3DEFORM_TEXT1:
8861                 case Q3DEFORM_TEXT2:
8862                 case Q3DEFORM_TEXT3:
8863                 case Q3DEFORM_TEXT4:
8864                 case Q3DEFORM_TEXT5:
8865                 case Q3DEFORM_TEXT6:
8866                 case Q3DEFORM_TEXT7:
8867                 case Q3DEFORM_NONE:
8868                         break;
8869                 case Q3DEFORM_AUTOSPRITE:
8870                         if (!dynamicvertex)
8871                         {
8872                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
8873                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
8874                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
8875                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
8876                         }
8877                         dynamicvertex = true;
8878                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8879                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8880                         break;
8881                 case Q3DEFORM_AUTOSPRITE2:
8882                         if (!dynamicvertex)
8883                         {
8884                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
8885                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
8886                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
8887                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
8888                         }
8889                         dynamicvertex = true;
8890                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8891                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8892                         break;
8893                 case Q3DEFORM_NORMAL:
8894                         if (!dynamicvertex)
8895                         {
8896                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
8897                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
8898                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
8899                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
8900                         }
8901                         dynamicvertex = true;
8902                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8903                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8904                         break;
8905                 case Q3DEFORM_WAVE:
8906                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8907                                 break; // if wavefunc is a nop, ignore this transform
8908                         if (!dynamicvertex)
8909                         {
8910                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
8911                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
8912                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
8913                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
8914                         }
8915                         dynamicvertex = true;
8916                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8917                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8918                         break;
8919                 case Q3DEFORM_BULGE:
8920                         if (!dynamicvertex)
8921                         {
8922                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
8923                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
8924                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
8925                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
8926                         }
8927                         dynamicvertex = true;
8928                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8929                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8930                         break;
8931                 case Q3DEFORM_MOVE:
8932                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8933                                 break; // if wavefunc is a nop, ignore this transform
8934                         if (!dynamicvertex)
8935                         {
8936                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
8937                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
8938                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
8939                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
8940                         }
8941                         dynamicvertex = true;
8942                         batchneed |= BATCHNEED_ARRAY_VERTEX;
8943                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8944                         break;
8945                 }
8946         }
8947         switch(rsurface.texture->tcgen.tcgen)
8948         {
8949         default:
8950         case Q3TCGEN_TEXTURE:
8951                 break;
8952         case Q3TCGEN_LIGHTMAP:
8953                 if (!dynamicvertex)
8954                 {
8955                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
8956                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
8957                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
8958                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
8959                 }
8960                 dynamicvertex = true;
8961                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8962                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8963                 break;
8964         case Q3TCGEN_VECTOR:
8965                 if (!dynamicvertex)
8966                 {
8967                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
8968                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
8969                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
8970                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
8971                 }
8972                 dynamicvertex = true;
8973                 batchneed |= BATCHNEED_ARRAY_VERTEX;
8974                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8975                 break;
8976         case Q3TCGEN_ENVIRONMENT:
8977                 if (!dynamicvertex)
8978                 {
8979                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
8980                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
8981                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
8982                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
8983                 }
8984                 dynamicvertex = true;
8985                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
8986                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8987                 break;
8988         }
8989         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8990         {
8991                 if (!dynamicvertex)
8992                 {
8993                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
8994                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
8995                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
8996                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
8997                 }
8998                 dynamicvertex = true;
8999                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9000                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9001         }
9002
9003         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9004         {
9005                 if (!dynamicvertex)
9006                 {
9007                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9008                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9009                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9010                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9011                 }
9012                 dynamicvertex = true;
9013                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9014         }
9015
9016         // when the model data has no vertex buffer (dynamic mesh), we need to
9017         // eliminate gaps
9018         if (vid.useinterleavedarrays && !rsurface.modelvertexmeshbuffer)
9019                 batchneed |= BATCHNEED_NOGAPS;
9020
9021         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9022         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9023         // we ensure this by treating the vertex batch as dynamic...
9024         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9025         {
9026                 if (!dynamicvertex)
9027                 {
9028                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9029                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9030                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9031                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9032                 }
9033                 dynamicvertex = true;
9034         }
9035
9036         if (dynamicvertex)
9037         {
9038                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9039                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9040                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9041                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9042                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9043                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9044                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9045                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9046         }
9047
9048         // if needsupdate, we have to do a dynamic vertex batch for sure
9049         if (needsupdate & batchneed)
9050         {
9051                 if (!dynamicvertex)
9052                 {
9053                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9054                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9055                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9056                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9057                 }
9058                 dynamicvertex = true;
9059         }
9060
9061         // see if we need to build vertexmesh from arrays
9062         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9063         {
9064                 if (!dynamicvertex)
9065                 {
9066                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9067                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9068                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9069                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9070                 }
9071                 dynamicvertex = true;
9072         }
9073
9074         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9075         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9076                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9077
9078         rsurface.batchvertex3f = rsurface.modelvertex3f;
9079         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9080         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9081         rsurface.batchsvector3f = rsurface.modelsvector3f;
9082         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9083         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9084         rsurface.batchtvector3f = rsurface.modeltvector3f;
9085         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9086         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9087         rsurface.batchnormal3f = rsurface.modelnormal3f;
9088         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9089         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9090         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9091         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9092         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9093         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9094         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9095         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9096         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9097         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9098         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9099         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9100         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9101         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9102         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9103         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9104         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9105         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
9106         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9107         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
9108         rsurface.batchelement3i = rsurface.modelelement3i;
9109         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9110         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9111         rsurface.batchelement3s = rsurface.modelelement3s;
9112         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9113         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9114         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9115         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9116
9117         // if any dynamic vertex processing has to occur in software, we copy the
9118         // entire surface list together before processing to rebase the vertices
9119         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9120         //
9121         // if any gaps exist and we do not have a static vertex buffer, we have to
9122         // copy the surface list together to avoid wasting upload bandwidth on the
9123         // vertices in the gaps.
9124         //
9125         // if gaps exist and we have a static vertex buffer, we can choose whether
9126         // to combine the index buffer ranges into one dynamic index buffer or
9127         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9128         //
9129         // in many cases the batch is reduced to one draw call.
9130
9131         rsurface.batchmultidraw = false;
9132         rsurface.batchmultidrawnumsurfaces = 0;
9133         rsurface.batchmultidrawsurfacelist = NULL;
9134
9135         if (!dynamicvertex)
9136         {
9137                 // static vertex data, just set pointers...
9138                 rsurface.batchgeneratedvertex = false;
9139                 // if there are gaps, we want to build a combined index buffer,
9140                 // otherwise use the original static buffer with an appropriate offset
9141                 if (gaps)
9142                 {
9143                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9144                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9145                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9146                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9147                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9148                         {
9149                                 rsurface.batchmultidraw = true;
9150                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9151                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9152                                 return;
9153                         }
9154                         // build a new triangle elements array for this batch
9155                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9156                         rsurface.batchfirsttriangle = 0;
9157                         numtriangles = 0;
9158                         for (i = 0;i < texturenumsurfaces;i++)
9159                         {
9160                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9161                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9162                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9163                                 numtriangles += surfacenumtriangles;
9164                         }
9165                         rsurface.batchelement3i_indexbuffer = NULL;
9166                         rsurface.batchelement3i_bufferoffset = 0;
9167                         rsurface.batchelement3s = NULL;
9168                         rsurface.batchelement3s_indexbuffer = NULL;
9169                         rsurface.batchelement3s_bufferoffset = 0;
9170                         if (endvertex <= 65536)
9171                         {
9172                                 // make a 16bit (unsigned short) index array if possible
9173                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9174                                 for (i = 0;i < numtriangles*3;i++)
9175                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9176                         }
9177                 }
9178                 else
9179                 {
9180                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9181                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9182                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9183                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9184                 }
9185                 return;
9186         }
9187
9188         // something needs software processing, do it for real...
9189         // we only directly handle separate array data in this case and then
9190         // generate interleaved data if needed...
9191         rsurface.batchgeneratedvertex = true;
9192         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9193         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9194         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9195         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9196
9197         // now copy the vertex data into a combined array and make an index array
9198         // (this is what Quake3 does all the time)
9199         // we also apply any skeletal animation here that would have been done in
9200         // the vertex shader, because most of the dynamic vertex animation cases
9201         // need actual vertex positions and normals
9202         //if (dynamicvertex)
9203         {
9204                 rsurface.batchvertex3fbuffer = NULL;
9205                 rsurface.batchvertexmesh = NULL;
9206                 rsurface.batchvertexmeshbuffer = NULL;
9207                 rsurface.batchvertex3f = NULL;
9208                 rsurface.batchvertex3f_vertexbuffer = NULL;
9209                 rsurface.batchvertex3f_bufferoffset = 0;
9210                 rsurface.batchsvector3f = NULL;
9211                 rsurface.batchsvector3f_vertexbuffer = NULL;
9212                 rsurface.batchsvector3f_bufferoffset = 0;
9213                 rsurface.batchtvector3f = NULL;
9214                 rsurface.batchtvector3f_vertexbuffer = NULL;
9215                 rsurface.batchtvector3f_bufferoffset = 0;
9216                 rsurface.batchnormal3f = NULL;
9217                 rsurface.batchnormal3f_vertexbuffer = NULL;
9218                 rsurface.batchnormal3f_bufferoffset = 0;
9219                 rsurface.batchlightmapcolor4f = NULL;
9220                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9221                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9222                 rsurface.batchtexcoordtexture2f = NULL;
9223                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9224                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9225                 rsurface.batchtexcoordlightmap2f = NULL;
9226                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9227                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9228                 rsurface.batchskeletalindex4ub = NULL;
9229                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9230                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9231                 rsurface.batchskeletalweight4ub = NULL;
9232                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9233                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9234                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9235                 rsurface.batchelement3i_indexbuffer = NULL;
9236                 rsurface.batchelement3i_bufferoffset = 0;
9237                 rsurface.batchelement3s = NULL;
9238                 rsurface.batchelement3s_indexbuffer = NULL;
9239                 rsurface.batchelement3s_bufferoffset = 0;
9240                 // we'll only be setting up certain arrays as needed
9241                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9242                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9243                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9244                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9245                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9246                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9247                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9248                 {
9249                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9250                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9251                 }
9252                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9253                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9254                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9255                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9256                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9257                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9258                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9259                 {
9260                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9261                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9262                 }
9263                 numvertices = 0;
9264                 numtriangles = 0;
9265                 for (i = 0;i < texturenumsurfaces;i++)
9266                 {
9267                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9268                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9269                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9270                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9271                         // copy only the data requested
9272                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9273                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9274                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9275                         {
9276                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9277                                 {
9278                                         if (rsurface.batchvertex3f)
9279                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9280                                         else
9281                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9282                                 }
9283                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9284                                 {
9285                                         if (rsurface.modelnormal3f)
9286                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9287                                         else
9288                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9289                                 }
9290                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9291                                 {
9292                                         if (rsurface.modelsvector3f)
9293                                         {
9294                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9295                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9296                                         }
9297                                         else
9298                                         {
9299                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9300                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9301                                         }
9302                                 }
9303                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9304                                 {
9305                                         if (rsurface.modellightmapcolor4f)
9306                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9307                                         else
9308                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9309                                 }
9310                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9311                                 {
9312                                         if (rsurface.modeltexcoordtexture2f)
9313                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9314                                         else
9315                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9316                                 }
9317                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9318                                 {
9319                                         if (rsurface.modeltexcoordlightmap2f)
9320                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9321                                         else
9322                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9323                                 }
9324                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9325                                 {
9326                                         if (rsurface.modelskeletalindex4ub)
9327                                         {
9328                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9329                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9330                                         }
9331                                         else
9332                                         {
9333                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9334                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9335                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9336                                                 for (j = 0;j < surfacenumvertices;j++)
9337                                                         ub[j*4] = 255;
9338                                         }
9339                                 }
9340                         }
9341                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9342                         numvertices += surfacenumvertices;
9343                         numtriangles += surfacenumtriangles;
9344                 }
9345
9346                 // generate a 16bit index array as well if possible
9347                 // (in general, dynamic batches fit)
9348                 if (numvertices <= 65536)
9349                 {
9350                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9351                         for (i = 0;i < numtriangles*3;i++)
9352                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9353                 }
9354
9355                 // since we've copied everything, the batch now starts at 0
9356                 rsurface.batchfirstvertex = 0;
9357                 rsurface.batchnumvertices = batchnumvertices;
9358                 rsurface.batchfirsttriangle = 0;
9359                 rsurface.batchnumtriangles = batchnumtriangles;
9360         }
9361
9362         // apply skeletal animation that would have been done in the vertex shader
9363         if (rsurface.batchskeletaltransform3x4)
9364         {
9365                 const unsigned char *si;
9366                 const unsigned char *sw;
9367                 const float *t[4];
9368                 const float *b = rsurface.batchskeletaltransform3x4;
9369                 float *vp, *vs, *vt, *vn;
9370                 float w[4];
9371                 float m[3][4], n[3][4];
9372                 float tp[3], ts[3], tt[3], tn[3];
9373                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9374                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9375                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9376                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9377                 si = rsurface.batchskeletalindex4ub;
9378                 sw = rsurface.batchskeletalweight4ub;
9379                 vp = rsurface.batchvertex3f;
9380                 vs = rsurface.batchsvector3f;
9381                 vt = rsurface.batchtvector3f;
9382                 vn = rsurface.batchnormal3f;
9383                 memset(m[0], 0, sizeof(m));
9384                 memset(n[0], 0, sizeof(n));
9385                 for (i = 0;i < batchnumvertices;i++)
9386                 {
9387                         t[0] = b + si[0]*12;
9388                         if (sw[0] == 255)
9389                         {
9390                                 // common case - only one matrix
9391                                 m[0][0] = t[0][ 0];
9392                                 m[0][1] = t[0][ 1];
9393                                 m[0][2] = t[0][ 2];
9394                                 m[0][3] = t[0][ 3];
9395                                 m[1][0] = t[0][ 4];
9396                                 m[1][1] = t[0][ 5];
9397                                 m[1][2] = t[0][ 6];
9398                                 m[1][3] = t[0][ 7];
9399                                 m[2][0] = t[0][ 8];
9400                                 m[2][1] = t[0][ 9];
9401                                 m[2][2] = t[0][10];
9402                                 m[2][3] = t[0][11];
9403                         }
9404                         else if (sw[2] + sw[3])
9405                         {
9406                                 // blend 4 matrices
9407                                 t[1] = b + si[1]*12;
9408                                 t[2] = b + si[2]*12;
9409                                 t[3] = b + si[3]*12;
9410                                 w[0] = sw[0] * (1.0f / 255.0f);
9411                                 w[1] = sw[1] * (1.0f / 255.0f);
9412                                 w[2] = sw[2] * (1.0f / 255.0f);
9413                                 w[3] = sw[3] * (1.0f / 255.0f);
9414                                 // blend the matrices
9415                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9416                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9417                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9418                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9419                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9420                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9421                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9422                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9423                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9424                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9425                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9426                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9427                         }
9428                         else
9429                         {
9430                                 // blend 2 matrices
9431                                 t[1] = b + si[1]*12;
9432                                 w[0] = sw[0] * (1.0f / 255.0f);
9433                                 w[1] = sw[1] * (1.0f / 255.0f);
9434                                 // blend the matrices
9435                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9436                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9437                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9438                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9439                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9440                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9441                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9442                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9443                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9444                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9445                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9446                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9447                         }
9448                         si += 4;
9449                         sw += 4;
9450                         // modify the vertex
9451                         VectorCopy(vp, tp);
9452                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9453                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9454                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9455                         vp += 3;
9456                         if (vn)
9457                         {
9458                                 // the normal transformation matrix is a set of cross products...
9459                                 CrossProduct(m[1], m[2], n[0]);
9460                                 CrossProduct(m[2], m[0], n[1]);
9461                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9462                                 VectorCopy(vn, tn);
9463                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9464                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9465                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9466                                 VectorNormalize(vn);
9467                                 vn += 3;
9468                                 if (vs)
9469                                 {
9470                                         VectorCopy(vs, ts);
9471                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9472                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9473                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9474                                         VectorNormalize(vs);
9475                                         vs += 3;
9476                                         VectorCopy(vt, tt);
9477                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9478                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9479                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9480                                         VectorNormalize(vt);
9481                                         vt += 3;
9482                                 }
9483                         }
9484                 }
9485                 rsurface.batchskeletaltransform3x4 = NULL;
9486                 rsurface.batchskeletalnumtransforms = 0;
9487         }
9488
9489         // q1bsp surfaces rendered in vertex color mode have to have colors
9490         // calculated based on lightstyles
9491         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9492         {
9493                 // generate color arrays for the surfaces in this list
9494                 int c[4];
9495                 int scale;
9496                 int size3;
9497                 const int *offsets;
9498                 const unsigned char *lm;
9499                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9500                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9501                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9502                 numvertices = 0;
9503                 for (i = 0;i < texturenumsurfaces;i++)
9504                 {
9505                         surface = texturesurfacelist[i];
9506                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9507                         surfacenumvertices = surface->num_vertices;
9508                         if (surface->lightmapinfo->samples)
9509                         {
9510                                 for (j = 0;j < surfacenumvertices;j++)
9511                                 {
9512                                         lm = surface->lightmapinfo->samples + offsets[j];
9513                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9514                                         VectorScale(lm, scale, c);
9515                                         if (surface->lightmapinfo->styles[1] != 255)
9516                                         {
9517                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9518                                                 lm += size3;
9519                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9520                                                 VectorMA(c, scale, lm, c);
9521                                                 if (surface->lightmapinfo->styles[2] != 255)
9522                                                 {
9523                                                         lm += size3;
9524                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9525                                                         VectorMA(c, scale, lm, c);
9526                                                         if (surface->lightmapinfo->styles[3] != 255)
9527                                                         {
9528                                                                 lm += size3;
9529                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9530                                                                 VectorMA(c, scale, lm, c);
9531                                                         }
9532                                                 }
9533                                         }
9534                                         c[0] >>= 7;
9535                                         c[1] >>= 7;
9536                                         c[2] >>= 7;
9537                                         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);
9538                                         numvertices++;
9539                                 }
9540                         }
9541                         else
9542                         {
9543                                 for (j = 0;j < surfacenumvertices;j++)
9544                                 {
9545                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9546                                         numvertices++;
9547                                 }
9548                         }
9549                 }
9550         }
9551
9552         // if vertices are deformed (sprite flares and things in maps, possibly
9553         // water waves, bulges and other deformations), modify the copied vertices
9554         // in place
9555         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9556         {
9557                 switch (deform->deform)
9558                 {
9559                 default:
9560                 case Q3DEFORM_PROJECTIONSHADOW:
9561                 case Q3DEFORM_TEXT0:
9562                 case Q3DEFORM_TEXT1:
9563                 case Q3DEFORM_TEXT2:
9564                 case Q3DEFORM_TEXT3:
9565                 case Q3DEFORM_TEXT4:
9566                 case Q3DEFORM_TEXT5:
9567                 case Q3DEFORM_TEXT6:
9568                 case Q3DEFORM_TEXT7:
9569                 case Q3DEFORM_NONE:
9570                         break;
9571                 case Q3DEFORM_AUTOSPRITE:
9572                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9573                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9574                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9575                         VectorNormalize(newforward);
9576                         VectorNormalize(newright);
9577                         VectorNormalize(newup);
9578 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9579 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9580 //                      rsurface.batchvertex3f_bufferoffset = 0;
9581 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9582 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9583 //                      rsurface.batchsvector3f_bufferoffset = 0;
9584 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9585 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9586 //                      rsurface.batchtvector3f_bufferoffset = 0;
9587 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9588 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9589 //                      rsurface.batchnormal3f_bufferoffset = 0;
9590                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9591                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9592                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9593                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9594                                 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);
9595                         // a single autosprite surface can contain multiple sprites...
9596                         for (j = 0;j < batchnumvertices - 3;j += 4)
9597                         {
9598                                 VectorClear(center);
9599                                 for (i = 0;i < 4;i++)
9600                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9601                                 VectorScale(center, 0.25f, center);
9602                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9603                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9604                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9605                                 for (i = 0;i < 4;i++)
9606                                 {
9607                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9608                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9609                                 }
9610                         }
9611                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9612                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9613                         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);
9614                         break;
9615                 case Q3DEFORM_AUTOSPRITE2:
9616                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9617                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9618                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9619                         VectorNormalize(newforward);
9620                         VectorNormalize(newright);
9621                         VectorNormalize(newup);
9622 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9623 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9624 //                      rsurface.batchvertex3f_bufferoffset = 0;
9625                         {
9626                                 const float *v1, *v2;
9627                                 vec3_t start, end;
9628                                 float f, l;
9629                                 struct
9630                                 {
9631                                         float length2;
9632                                         const float *v1;
9633                                         const float *v2;
9634                                 }
9635                                 shortest[2];
9636                                 memset(shortest, 0, sizeof(shortest));
9637                                 // a single autosprite surface can contain multiple sprites...
9638                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9639                                 {
9640                                         VectorClear(center);
9641                                         for (i = 0;i < 4;i++)
9642                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9643                                         VectorScale(center, 0.25f, center);
9644                                         // find the two shortest edges, then use them to define the
9645                                         // axis vectors for rotating around the central axis
9646                                         for (i = 0;i < 6;i++)
9647                                         {
9648                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9649                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9650                                                 l = VectorDistance2(v1, v2);
9651                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9652                                                 if (v1[2] != v2[2])
9653                                                         l += (1.0f / 1024.0f);
9654                                                 if (shortest[0].length2 > l || i == 0)
9655                                                 {
9656                                                         shortest[1] = shortest[0];
9657                                                         shortest[0].length2 = l;
9658                                                         shortest[0].v1 = v1;
9659                                                         shortest[0].v2 = v2;
9660                                                 }
9661                                                 else if (shortest[1].length2 > l || i == 1)
9662                                                 {
9663                                                         shortest[1].length2 = l;
9664                                                         shortest[1].v1 = v1;
9665                                                         shortest[1].v2 = v2;
9666                                                 }
9667                                         }
9668                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9669                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9670                                         // this calculates the right vector from the shortest edge
9671                                         // and the up vector from the edge midpoints
9672                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9673                                         VectorNormalize(right);
9674                                         VectorSubtract(end, start, up);
9675                                         VectorNormalize(up);
9676                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9677                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9678                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9679                                         VectorNegate(forward, forward);
9680                                         VectorReflect(forward, 0, up, forward);
9681                                         VectorNormalize(forward);
9682                                         CrossProduct(up, forward, newright);
9683                                         VectorNormalize(newright);
9684                                         // rotate the quad around the up axis vector, this is made
9685                                         // especially easy by the fact we know the quad is flat,
9686                                         // so we only have to subtract the center position and
9687                                         // measure distance along the right vector, and then
9688                                         // multiply that by the newright vector and add back the
9689                                         // center position
9690                                         // we also need to subtract the old position to undo the
9691                                         // displacement from the center, which we do with a
9692                                         // DotProduct, the subtraction/addition of center is also
9693                                         // optimized into DotProducts here
9694                                         l = DotProduct(right, center);
9695                                         for (i = 0;i < 4;i++)
9696                                         {
9697                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9698                                                 f = DotProduct(right, v1) - l;
9699                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9700                                         }
9701                                 }
9702                         }
9703                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9704                         {
9705 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9706 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9707 //                              rsurface.batchnormal3f_bufferoffset = 0;
9708                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9709                         }
9710                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9711                         {
9712 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9713 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9714 //                              rsurface.batchsvector3f_bufferoffset = 0;
9715 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9716 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9717 //                              rsurface.batchtvector3f_bufferoffset = 0;
9718                                 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);
9719                         }
9720                         break;
9721                 case Q3DEFORM_NORMAL:
9722                         // deform the normals to make reflections wavey
9723                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9724                         rsurface.batchnormal3f_vertexbuffer = NULL;
9725                         rsurface.batchnormal3f_bufferoffset = 0;
9726                         for (j = 0;j < batchnumvertices;j++)
9727                         {
9728                                 float vertex[3];
9729                                 float *normal = rsurface.batchnormal3f + 3*j;
9730                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9731                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9732                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9733                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9734                                 VectorNormalize(normal);
9735                         }
9736                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9737                         {
9738 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9739 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9740 //                              rsurface.batchsvector3f_bufferoffset = 0;
9741 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9742 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9743 //                              rsurface.batchtvector3f_bufferoffset = 0;
9744                                 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);
9745                         }
9746                         break;
9747                 case Q3DEFORM_WAVE:
9748                         // deform vertex array to make wavey water and flags and such
9749                         waveparms[0] = deform->waveparms[0];
9750                         waveparms[1] = deform->waveparms[1];
9751                         waveparms[2] = deform->waveparms[2];
9752                         waveparms[3] = deform->waveparms[3];
9753                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9754                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9755                         // this is how a divisor of vertex influence on deformation
9756                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9757                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9758 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9759 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9760 //                      rsurface.batchvertex3f_bufferoffset = 0;
9761 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9762 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9763 //                      rsurface.batchnormal3f_bufferoffset = 0;
9764                         for (j = 0;j < batchnumvertices;j++)
9765                         {
9766                                 // if the wavefunc depends on time, evaluate it per-vertex
9767                                 if (waveparms[3])
9768                                 {
9769                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9770                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9771                                 }
9772                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9773                         }
9774                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9775                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9776                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9777                         {
9778 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9779 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9780 //                              rsurface.batchsvector3f_bufferoffset = 0;
9781 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9782 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9783 //                              rsurface.batchtvector3f_bufferoffset = 0;
9784                                 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);
9785                         }
9786                         break;
9787                 case Q3DEFORM_BULGE:
9788                         // deform vertex array to make the surface have moving bulges
9789 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9790 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9791 //                      rsurface.batchvertex3f_bufferoffset = 0;
9792 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9793 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9794 //                      rsurface.batchnormal3f_bufferoffset = 0;
9795                         for (j = 0;j < batchnumvertices;j++)
9796                         {
9797                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9798                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9799                         }
9800                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9801                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9802                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9803                         {
9804 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9805 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9806 //                              rsurface.batchsvector3f_bufferoffset = 0;
9807 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9808 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9809 //                              rsurface.batchtvector3f_bufferoffset = 0;
9810                                 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);
9811                         }
9812                         break;
9813                 case Q3DEFORM_MOVE:
9814                         // deform vertex array
9815                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9816                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9817                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9818                         VectorScale(deform->parms, scale, waveparms);
9819 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9820 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9821 //                      rsurface.batchvertex3f_bufferoffset = 0;
9822                         for (j = 0;j < batchnumvertices;j++)
9823                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9824                         break;
9825                 }
9826         }
9827
9828         // generate texcoords based on the chosen texcoord source
9829         switch(rsurface.texture->tcgen.tcgen)
9830         {
9831         default:
9832         case Q3TCGEN_TEXTURE:
9833                 break;
9834         case Q3TCGEN_LIGHTMAP:
9835 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9836 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9837 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9838                 if (rsurface.batchtexcoordlightmap2f)
9839                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9840                 break;
9841         case Q3TCGEN_VECTOR:
9842 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9843 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9844 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9845                 for (j = 0;j < batchnumvertices;j++)
9846                 {
9847                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9848                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9849                 }
9850                 break;
9851         case Q3TCGEN_ENVIRONMENT:
9852                 // make environment reflections using a spheremap
9853                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9854                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9855                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9856                 for (j = 0;j < batchnumvertices;j++)
9857                 {
9858                         // identical to Q3A's method, but executed in worldspace so
9859                         // carried models can be shiny too
9860
9861                         float viewer[3], d, reflected[3], worldreflected[3];
9862
9863                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9864                         // VectorNormalize(viewer);
9865
9866                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9867
9868                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9869                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9870                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9871                         // note: this is proportinal to viewer, so we can normalize later
9872
9873                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9874                         VectorNormalize(worldreflected);
9875
9876                         // note: this sphere map only uses world x and z!
9877                         // so positive and negative y will LOOK THE SAME.
9878                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9879                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9880                 }
9881                 break;
9882         }
9883         // the only tcmod that needs software vertex processing is turbulent, so
9884         // check for it here and apply the changes if needed
9885         // and we only support that as the first one
9886         // (handling a mixture of turbulent and other tcmods would be problematic
9887         //  without punting it entirely to a software path)
9888         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9889         {
9890                 amplitude = rsurface.texture->tcmods[0].parms[1];
9891                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9892 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9893 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9894 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9895                 for (j = 0;j < batchnumvertices;j++)
9896                 {
9897                         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);
9898                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9899                 }
9900         }
9901
9902         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9903         {
9904                 // convert the modified arrays to vertex structs
9905 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9906 //              rsurface.batchvertexmeshbuffer = NULL;
9907                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9908                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9909                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9910                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9911                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9912                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9913                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9914                 {
9915                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9916                         {
9917                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9918                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9919                         }
9920                 }
9921                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9922                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9923                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9924                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9925                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9926                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9927                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9928                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9929                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9930                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9931                 {
9932                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9933                         {
9934                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9935                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9936                         }
9937                 }
9938         }
9939 }
9940
9941 void RSurf_DrawBatch(void)
9942 {
9943         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9944         // through the pipeline, killing it earlier in the pipeline would have
9945         // per-surface overhead rather than per-batch overhead, so it's best to
9946         // reject it here, before it hits glDraw.
9947         if (rsurface.batchnumtriangles == 0)
9948                 return;
9949 #if 0
9950         // batch debugging code
9951         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9952         {
9953                 int i;
9954                 int j;
9955                 int c;
9956                 const int *e;
9957                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9958                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9959                 {
9960                         c = e[i];
9961                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9962                         {
9963                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9964                                 {
9965                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9966                                                 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);
9967                                         break;
9968                                 }
9969                         }
9970                 }
9971         }
9972 #endif
9973         if (rsurface.batchmultidraw)
9974         {
9975                 // issue multiple draws rather than copying index data
9976                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
9977                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
9978                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
9979                 for (i = 0;i < numsurfaces;)
9980                 {
9981                         // combine consecutive surfaces as one draw
9982                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
9983                                 if (surfacelist[j] != surfacelist[k] + 1)
9984                                         break;
9985                         firstvertex = surfacelist[i]->num_firstvertex;
9986                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
9987                         firsttriangle = surfacelist[i]->num_firsttriangle;
9988                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
9989                         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);
9990                         i = j;
9991                 }
9992         }
9993         else
9994         {
9995                 // there is only one consecutive run of index data (may have been combined)
9996                 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);
9997         }
9998 }
9999
10000 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10001 {
10002         // pick the closest matching water plane
10003         int planeindex, vertexindex, bestplaneindex = -1;
10004         float d, bestd;
10005         vec3_t vert;
10006         const float *v;
10007         r_waterstate_waterplane_t *p;
10008         qboolean prepared = false;
10009         bestd = 0;
10010         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10011         {
10012                 if(p->camera_entity != rsurface.texture->camera_entity)
10013                         continue;
10014                 d = 0;
10015                 if(!prepared)
10016                 {
10017                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10018                         prepared = true;
10019                         if(rsurface.batchnumvertices == 0)
10020                                 break;
10021                 }
10022                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10023                 {
10024                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10025                         d += fabs(PlaneDiff(vert, &p->plane));
10026                 }
10027                 if (bestd > d || bestplaneindex < 0)
10028                 {
10029                         bestd = d;
10030                         bestplaneindex = planeindex;
10031                 }
10032         }
10033         return bestplaneindex;
10034         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10035         // this situation though, as it might be better to render single larger
10036         // batches with useless stuff (backface culled for example) than to
10037         // render multiple smaller batches
10038 }
10039
10040 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10041 {
10042         int i;
10043         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10044         rsurface.passcolor4f_vertexbuffer = 0;
10045         rsurface.passcolor4f_bufferoffset = 0;
10046         for (i = 0;i < rsurface.batchnumvertices;i++)
10047                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10048 }
10049
10050 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10051 {
10052         int i;
10053         float f;
10054         const float *v;
10055         const float *c;
10056         float *c2;
10057         if (rsurface.passcolor4f)
10058         {
10059                 // generate color arrays
10060                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10061                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10062                 rsurface.passcolor4f_vertexbuffer = 0;
10063                 rsurface.passcolor4f_bufferoffset = 0;
10064                 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)
10065                 {
10066                         f = RSurf_FogVertex(v);
10067                         c2[0] = c[0] * f;
10068                         c2[1] = c[1] * f;
10069                         c2[2] = c[2] * f;
10070                         c2[3] = c[3];
10071                 }
10072         }
10073         else
10074         {
10075                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10076                 rsurface.passcolor4f_vertexbuffer = 0;
10077                 rsurface.passcolor4f_bufferoffset = 0;
10078                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10079                 {
10080                         f = RSurf_FogVertex(v);
10081                         c2[0] = f;
10082                         c2[1] = f;
10083                         c2[2] = f;
10084                         c2[3] = 1;
10085                 }
10086         }
10087 }
10088
10089 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10090 {
10091         int i;
10092         float f;
10093         const float *v;
10094         const float *c;
10095         float *c2;
10096         if (!rsurface.passcolor4f)
10097                 return;
10098         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10099         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10100         rsurface.passcolor4f_vertexbuffer = 0;
10101         rsurface.passcolor4f_bufferoffset = 0;
10102         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)
10103         {
10104                 f = RSurf_FogVertex(v);
10105                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10106                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10107                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10108                 c2[3] = c[3];
10109         }
10110 }
10111
10112 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10113 {
10114         int i;
10115         const float *c;
10116         float *c2;
10117         if (!rsurface.passcolor4f)
10118                 return;
10119         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10120         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10121         rsurface.passcolor4f_vertexbuffer = 0;
10122         rsurface.passcolor4f_bufferoffset = 0;
10123         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10124         {
10125                 c2[0] = c[0] * r;
10126                 c2[1] = c[1] * g;
10127                 c2[2] = c[2] * b;
10128                 c2[3] = c[3] * a;
10129         }
10130 }
10131
10132 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10133 {
10134         int i;
10135         const float *c;
10136         float *c2;
10137         if (!rsurface.passcolor4f)
10138                 return;
10139         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10140         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10141         rsurface.passcolor4f_vertexbuffer = 0;
10142         rsurface.passcolor4f_bufferoffset = 0;
10143         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10144         {
10145                 c2[0] = c[0] + r_refdef.scene.ambient;
10146                 c2[1] = c[1] + r_refdef.scene.ambient;
10147                 c2[2] = c[2] + r_refdef.scene.ambient;
10148                 c2[3] = c[3];
10149         }
10150 }
10151
10152 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10153 {
10154         // TODO: optimize
10155         rsurface.passcolor4f = NULL;
10156         rsurface.passcolor4f_vertexbuffer = 0;
10157         rsurface.passcolor4f_bufferoffset = 0;
10158         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10159         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10160         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10161         GL_Color(r, g, b, a);
10162         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10163         RSurf_DrawBatch();
10164 }
10165
10166 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10167 {
10168         // TODO: optimize applyfog && applycolor case
10169         // just apply fog if necessary, and tint the fog color array if necessary
10170         rsurface.passcolor4f = NULL;
10171         rsurface.passcolor4f_vertexbuffer = 0;
10172         rsurface.passcolor4f_bufferoffset = 0;
10173         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10174         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10175         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10176         GL_Color(r, g, b, a);
10177         RSurf_DrawBatch();
10178 }
10179
10180 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10181 {
10182         // TODO: optimize
10183         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10184         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10185         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10186         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10187         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10188         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10189         GL_Color(r, g, b, a);
10190         RSurf_DrawBatch();
10191 }
10192
10193 static void RSurf_DrawBatch_GL11_ClampColor(void)
10194 {
10195         int i;
10196         const float *c1;
10197         float *c2;
10198         if (!rsurface.passcolor4f)
10199                 return;
10200         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10201         {
10202                 c2[0] = bound(0.0f, c1[0], 1.0f);
10203                 c2[1] = bound(0.0f, c1[1], 1.0f);
10204                 c2[2] = bound(0.0f, c1[2], 1.0f);
10205                 c2[3] = bound(0.0f, c1[3], 1.0f);
10206         }
10207 }
10208
10209 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10210 {
10211         int i;
10212         float f;
10213         const float *v;
10214         const float *n;
10215         float *c;
10216         //vec3_t eyedir;
10217
10218         // fake shading
10219         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10220         rsurface.passcolor4f_vertexbuffer = 0;
10221         rsurface.passcolor4f_bufferoffset = 0;
10222         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)
10223         {
10224                 f = -DotProduct(r_refdef.view.forward, n);
10225                 f = max(0, f);
10226                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10227                 f *= r_refdef.lightmapintensity;
10228                 Vector4Set(c, f, f, f, 1);
10229         }
10230 }
10231
10232 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10233 {
10234         RSurf_DrawBatch_GL11_ApplyFakeLight();
10235         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10236         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10237         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10238         GL_Color(r, g, b, a);
10239         RSurf_DrawBatch();
10240 }
10241
10242 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10243 {
10244         int i;
10245         float f;
10246         float alpha;
10247         const float *v;
10248         const float *n;
10249         float *c;
10250         vec3_t ambientcolor;
10251         vec3_t diffusecolor;
10252         vec3_t lightdir;
10253         // TODO: optimize
10254         // model lighting
10255         VectorCopy(rsurface.modellight_lightdir, lightdir);
10256         f = 0.5f * r_refdef.lightmapintensity;
10257         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10258         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10259         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10260         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10261         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10262         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10263         alpha = *a;
10264         if (VectorLength2(diffusecolor) > 0)
10265         {
10266                 // q3-style directional shading
10267                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10268                 rsurface.passcolor4f_vertexbuffer = 0;
10269                 rsurface.passcolor4f_bufferoffset = 0;
10270                 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)
10271                 {
10272                         if ((f = DotProduct(n, lightdir)) > 0)
10273                                 VectorMA(ambientcolor, f, diffusecolor, c);
10274                         else
10275                                 VectorCopy(ambientcolor, c);
10276                         c[3] = alpha;
10277                 }
10278                 *r = 1;
10279                 *g = 1;
10280                 *b = 1;
10281                 *a = 1;
10282                 *applycolor = false;
10283         }
10284         else
10285         {
10286                 *r = ambientcolor[0];
10287                 *g = ambientcolor[1];
10288                 *b = ambientcolor[2];
10289                 rsurface.passcolor4f = NULL;
10290                 rsurface.passcolor4f_vertexbuffer = 0;
10291                 rsurface.passcolor4f_bufferoffset = 0;
10292         }
10293 }
10294
10295 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10296 {
10297         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10298         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10299         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10300         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10301         GL_Color(r, g, b, a);
10302         RSurf_DrawBatch();
10303 }
10304
10305 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10306 {
10307         int i;
10308         float f;
10309         const float *v;
10310         float *c;
10311
10312         // fake shading
10313         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10314         rsurface.passcolor4f_vertexbuffer = 0;
10315         rsurface.passcolor4f_bufferoffset = 0;
10316
10317         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10318         {
10319                 f = 1 - RSurf_FogVertex(v);
10320                 c[0] = r;
10321                 c[1] = g;
10322                 c[2] = b;
10323                 c[3] = f * a;
10324         }
10325 }
10326
10327 void RSurf_SetupDepthAndCulling(void)
10328 {
10329         // submodels are biased to avoid z-fighting with world surfaces that they
10330         // may be exactly overlapping (avoids z-fighting artifacts on certain
10331         // doors and things in Quake maps)
10332         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10333         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10334         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10335         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10336 }
10337
10338 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10339 {
10340         // transparent sky would be ridiculous
10341         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10342                 return;
10343         R_SetupShader_Generic_NoTexture(false, false);
10344         skyrenderlater = true;
10345         RSurf_SetupDepthAndCulling();
10346         GL_DepthMask(true);
10347         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10348         // skymasking on them, and Quake3 never did sky masking (unlike
10349         // software Quake and software Quake2), so disable the sky masking
10350         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10351         // and skymasking also looks very bad when noclipping outside the
10352         // level, so don't use it then either.
10353         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10354         {
10355                 R_Mesh_ResetTextureState();
10356                 if (skyrendermasked)
10357                 {
10358                         R_SetupShader_DepthOrShadow(false, false, false);
10359                         // depth-only (masking)
10360                         GL_ColorMask(0,0,0,0);
10361                         // just to make sure that braindead drivers don't draw
10362                         // anything despite that colormask...
10363                         GL_BlendFunc(GL_ZERO, GL_ONE);
10364                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10365                         if (rsurface.batchvertex3fbuffer)
10366                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10367                         else
10368                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10369                 }
10370                 else
10371                 {
10372                         R_SetupShader_Generic_NoTexture(false, false);
10373                         // fog sky
10374                         GL_BlendFunc(GL_ONE, GL_ZERO);
10375                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10376                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10377                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10378                 }
10379                 RSurf_DrawBatch();
10380                 if (skyrendermasked)
10381                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10382         }
10383         R_Mesh_ResetTextureState();
10384         GL_Color(1, 1, 1, 1);
10385 }
10386
10387 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10388 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10389 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10390 {
10391         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10392                 return;
10393         if (prepass)
10394         {
10395                 // render screenspace normalmap to texture
10396                 GL_DepthMask(true);
10397                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10398                 RSurf_DrawBatch();
10399                 return;
10400         }
10401
10402         // bind lightmap texture
10403
10404         // water/refraction/reflection/camera surfaces have to be handled specially
10405         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10406         {
10407                 int start, end, startplaneindex;
10408                 for (start = 0;start < texturenumsurfaces;start = end)
10409                 {
10410                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10411                         if(startplaneindex < 0)
10412                         {
10413                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10414                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10415                                 end = start + 1;
10416                                 continue;
10417                         }
10418                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10419                                 ;
10420                         // now that we have a batch using the same planeindex, render it
10421                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10422                         {
10423                                 // render water or distortion background
10424                                 GL_DepthMask(true);
10425                                 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);
10426                                 RSurf_DrawBatch();
10427                                 // blend surface on top
10428                                 GL_DepthMask(false);
10429                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10430                                 RSurf_DrawBatch();
10431                         }
10432                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10433                         {
10434                                 // render surface with reflection texture as input
10435                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10436                                 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);
10437                                 RSurf_DrawBatch();
10438                         }
10439                 }
10440                 return;
10441         }
10442
10443         // render surface batch normally
10444         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10445         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);
10446         RSurf_DrawBatch();
10447 }
10448
10449 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10450 {
10451         // OpenGL 1.3 path - anything not completely ancient
10452         qboolean applycolor;
10453         qboolean applyfog;
10454         int layerindex;
10455         const texturelayer_t *layer;
10456         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);
10457         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10458
10459         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10460         {
10461                 vec4_t layercolor;
10462                 int layertexrgbscale;
10463                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10464                 {
10465                         if (layerindex == 0)
10466                                 GL_AlphaTest(true);
10467                         else
10468                         {
10469                                 GL_AlphaTest(false);
10470                                 GL_DepthFunc(GL_EQUAL);
10471                         }
10472                 }
10473                 GL_DepthMask(layer->depthmask && writedepth);
10474                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10475                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10476                 {
10477                         layertexrgbscale = 4;
10478                         VectorScale(layer->color, 0.25f, layercolor);
10479                 }
10480                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10481                 {
10482                         layertexrgbscale = 2;
10483                         VectorScale(layer->color, 0.5f, layercolor);
10484                 }
10485                 else
10486                 {
10487                         layertexrgbscale = 1;
10488                         VectorScale(layer->color, 1.0f, layercolor);
10489                 }
10490                 layercolor[3] = layer->color[3];
10491                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10492                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10493                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10494                 switch (layer->type)
10495                 {
10496                 case TEXTURELAYERTYPE_LITTEXTURE:
10497                         // single-pass lightmapped texture with 2x rgbscale
10498                         R_Mesh_TexBind(0, r_texture_white);
10499                         R_Mesh_TexMatrix(0, NULL);
10500                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10501                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10502                         R_Mesh_TexBind(1, layer->texture);
10503                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10504                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10505                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10506                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10507                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10508                         else if (FAKELIGHT_ENABLED)
10509                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10510                         else if (rsurface.uselightmaptexture)
10511                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10512                         else
10513                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10514                         break;
10515                 case TEXTURELAYERTYPE_TEXTURE:
10516                         // singletexture unlit texture with transparency support
10517                         R_Mesh_TexBind(0, layer->texture);
10518                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10519                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10520                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10521                         R_Mesh_TexBind(1, 0);
10522                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10523                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10524                         break;
10525                 case TEXTURELAYERTYPE_FOG:
10526                         // singletexture fogging
10527                         if (layer->texture)
10528                         {
10529                                 R_Mesh_TexBind(0, layer->texture);
10530                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10531                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10532                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10533                         }
10534                         else
10535                         {
10536                                 R_Mesh_TexBind(0, 0);
10537                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10538                         }
10539                         R_Mesh_TexBind(1, 0);
10540                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10541                         // generate a color array for the fog pass
10542                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10543                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10544                         RSurf_DrawBatch();
10545                         break;
10546                 default:
10547                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10548                 }
10549         }
10550         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10551         {
10552                 GL_DepthFunc(GL_LEQUAL);
10553                 GL_AlphaTest(false);
10554         }
10555 }
10556
10557 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10558 {
10559         // OpenGL 1.1 - crusty old voodoo path
10560         qboolean applyfog;
10561         int layerindex;
10562         const texturelayer_t *layer;
10563         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);
10564         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10565
10566         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10567         {
10568                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10569                 {
10570                         if (layerindex == 0)
10571                                 GL_AlphaTest(true);
10572                         else
10573                         {
10574                                 GL_AlphaTest(false);
10575                                 GL_DepthFunc(GL_EQUAL);
10576                         }
10577                 }
10578                 GL_DepthMask(layer->depthmask && writedepth);
10579                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10580                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10581                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10582                 switch (layer->type)
10583                 {
10584                 case TEXTURELAYERTYPE_LITTEXTURE:
10585                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10586                         {
10587                                 // two-pass lit texture with 2x rgbscale
10588                                 // first the lightmap pass
10589                                 R_Mesh_TexBind(0, r_texture_white);
10590                                 R_Mesh_TexMatrix(0, NULL);
10591                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10592                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10593                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10594                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10595                                 else if (FAKELIGHT_ENABLED)
10596                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10597                                 else if (rsurface.uselightmaptexture)
10598                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10599                                 else
10600                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10601                                 // then apply the texture to it
10602                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10603                                 R_Mesh_TexBind(0, layer->texture);
10604                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10605                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10606                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10607                                 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);
10608                         }
10609                         else
10610                         {
10611                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10612                                 R_Mesh_TexBind(0, layer->texture);
10613                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10614                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10615                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10616                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10617                                         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);
10618                                 else if (FAKELIGHT_ENABLED)
10619                                         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);
10620                                 else
10621                                         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);
10622                         }
10623                         break;
10624                 case TEXTURELAYERTYPE_TEXTURE:
10625                         // singletexture unlit texture with transparency support
10626                         R_Mesh_TexBind(0, layer->texture);
10627                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10628                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10629                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10630                         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);
10631                         break;
10632                 case TEXTURELAYERTYPE_FOG:
10633                         // singletexture fogging
10634                         if (layer->texture)
10635                         {
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                         }
10641                         else
10642                         {
10643                                 R_Mesh_TexBind(0, 0);
10644                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10645                         }
10646                         // generate a color array for the fog pass
10647                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10648                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10649                         RSurf_DrawBatch();
10650                         break;
10651                 default:
10652                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10653                 }
10654         }
10655         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10656         {
10657                 GL_DepthFunc(GL_LEQUAL);
10658                 GL_AlphaTest(false);
10659         }
10660 }
10661
10662 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10663 {
10664         int vi;
10665         int j;
10666         r_vertexgeneric_t *batchvertex;
10667         float c[4];
10668
10669 //      R_Mesh_ResetTextureState();
10670         R_SetupShader_Generic_NoTexture(false, false);
10671
10672         if(rsurface.texture && rsurface.texture->currentskinframe)
10673         {
10674                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10675                 c[3] *= rsurface.texture->currentalpha;
10676         }
10677         else
10678         {
10679                 c[0] = 1;
10680                 c[1] = 0;
10681                 c[2] = 1;
10682                 c[3] = 1;
10683         }
10684
10685         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10686         {
10687                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10688                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10689                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10690         }
10691
10692         // brighten it up (as texture value 127 means "unlit")
10693         c[0] *= 2 * r_refdef.view.colorscale;
10694         c[1] *= 2 * r_refdef.view.colorscale;
10695         c[2] *= 2 * r_refdef.view.colorscale;
10696
10697         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10698                 c[3] *= r_wateralpha.value;
10699
10700         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10701         {
10702                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10703                 GL_DepthMask(false);
10704         }
10705         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10706         {
10707                 GL_BlendFunc(GL_ONE, GL_ONE);
10708                 GL_DepthMask(false);
10709         }
10710         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10711         {
10712                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10713                 GL_DepthMask(false);
10714         }
10715         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10716         {
10717                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10718                 GL_DepthMask(false);
10719         }
10720         else
10721         {
10722                 GL_BlendFunc(GL_ONE, GL_ZERO);
10723                 GL_DepthMask(writedepth);
10724         }
10725
10726         if (r_showsurfaces.integer == 3)
10727         {
10728                 rsurface.passcolor4f = NULL;
10729
10730                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10731                 {
10732                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10733
10734                         rsurface.passcolor4f = NULL;
10735                         rsurface.passcolor4f_vertexbuffer = 0;
10736                         rsurface.passcolor4f_bufferoffset = 0;
10737                 }
10738                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10739                 {
10740                         qboolean applycolor = true;
10741                         float one = 1.0;
10742
10743                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10744
10745                         r_refdef.lightmapintensity = 1;
10746                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10747                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10748                 }
10749                 else if (FAKELIGHT_ENABLED)
10750                 {
10751                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10752
10753                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10754                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10755                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10756                 }
10757                 else
10758                 {
10759                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10760
10761                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10762                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10763                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10764                 }
10765
10766                 if(!rsurface.passcolor4f)
10767                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10768
10769                 RSurf_DrawBatch_GL11_ApplyAmbient();
10770                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10771                 if(r_refdef.fogenabled)
10772                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10773                 RSurf_DrawBatch_GL11_ClampColor();
10774
10775                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10776                 R_SetupShader_Generic_NoTexture(false, false);
10777                 RSurf_DrawBatch();
10778         }
10779         else if (!r_refdef.view.showdebug)
10780         {
10781                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10782                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10783                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10784                 {
10785                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10786                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10787                 }
10788                 R_Mesh_PrepareVertices_Generic_Unlock();
10789                 RSurf_DrawBatch();
10790         }
10791         else if (r_showsurfaces.integer == 4)
10792         {
10793                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10794                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10795                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10796                 {
10797                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10798                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10799                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10800                 }
10801                 R_Mesh_PrepareVertices_Generic_Unlock();
10802                 RSurf_DrawBatch();
10803         }
10804         else if (r_showsurfaces.integer == 2)
10805         {
10806                 const int *e;
10807                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10808                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10809                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10810                 {
10811                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10812                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10813                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10814                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10815                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10816                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10817                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10818                 }
10819                 R_Mesh_PrepareVertices_Generic_Unlock();
10820                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10821         }
10822         else
10823         {
10824                 int texturesurfaceindex;
10825                 int k;
10826                 const msurface_t *surface;
10827                 float surfacecolor4f[4];
10828                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10829                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10830                 vi = 0;
10831                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10832                 {
10833                         surface = texturesurfacelist[texturesurfaceindex];
10834                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10835                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10836                         for (j = 0;j < surface->num_vertices;j++)
10837                         {
10838                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10839                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10840                                 vi++;
10841                         }
10842                 }
10843                 R_Mesh_PrepareVertices_Generic_Unlock();
10844                 RSurf_DrawBatch();
10845         }
10846 }
10847
10848 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10849 {
10850         CHECKGLERROR
10851         RSurf_SetupDepthAndCulling();
10852         if (r_showsurfaces.integer)
10853         {
10854                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10855                 return;
10856         }
10857         switch (vid.renderpath)
10858         {
10859         case RENDERPATH_GL20:
10860         case RENDERPATH_D3D9:
10861         case RENDERPATH_D3D10:
10862         case RENDERPATH_D3D11:
10863         case RENDERPATH_SOFT:
10864         case RENDERPATH_GLES2:
10865                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10866                 break;
10867         case RENDERPATH_GL13:
10868         case RENDERPATH_GLES1:
10869                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10870                 break;
10871         case RENDERPATH_GL11:
10872                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10873                 break;
10874         }
10875         CHECKGLERROR
10876 }
10877
10878 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10879 {
10880         CHECKGLERROR
10881         RSurf_SetupDepthAndCulling();
10882         if (r_showsurfaces.integer)
10883         {
10884                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10885                 return;
10886         }
10887         switch (vid.renderpath)
10888         {
10889         case RENDERPATH_GL20:
10890         case RENDERPATH_D3D9:
10891         case RENDERPATH_D3D10:
10892         case RENDERPATH_D3D11:
10893         case RENDERPATH_SOFT:
10894         case RENDERPATH_GLES2:
10895                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10896                 break;
10897         case RENDERPATH_GL13:
10898         case RENDERPATH_GLES1:
10899                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10900                 break;
10901         case RENDERPATH_GL11:
10902                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10903                 break;
10904         }
10905         CHECKGLERROR
10906 }
10907
10908 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10909 {
10910         int i, j;
10911         int texturenumsurfaces, endsurface;
10912         texture_t *texture;
10913         const msurface_t *surface;
10914         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10915
10916         // if the model is static it doesn't matter what value we give for
10917         // wantnormals and wanttangents, so this logic uses only rules applicable
10918         // to a model, knowing that they are meaningless otherwise
10919         if (ent == r_refdef.scene.worldentity)
10920                 RSurf_ActiveWorldEntity();
10921         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10922                 RSurf_ActiveModelEntity(ent, false, false, false);
10923         else
10924         {
10925                 switch (vid.renderpath)
10926                 {
10927                 case RENDERPATH_GL20:
10928                 case RENDERPATH_D3D9:
10929                 case RENDERPATH_D3D10:
10930                 case RENDERPATH_D3D11:
10931                 case RENDERPATH_SOFT:
10932                 case RENDERPATH_GLES2:
10933                         RSurf_ActiveModelEntity(ent, true, true, false);
10934                         break;
10935                 case RENDERPATH_GL11:
10936                 case RENDERPATH_GL13:
10937                 case RENDERPATH_GLES1:
10938                         RSurf_ActiveModelEntity(ent, true, false, false);
10939                         break;
10940                 }
10941         }
10942
10943         if (r_transparentdepthmasking.integer)
10944         {
10945                 qboolean setup = false;
10946                 for (i = 0;i < numsurfaces;i = j)
10947                 {
10948                         j = i + 1;
10949                         surface = rsurface.modelsurfaces + surfacelist[i];
10950                         texture = surface->texture;
10951                         rsurface.texture = R_GetCurrentTexture(texture);
10952                         rsurface.lightmaptexture = NULL;
10953                         rsurface.deluxemaptexture = NULL;
10954                         rsurface.uselightmaptexture = false;
10955                         // scan ahead until we find a different texture
10956                         endsurface = min(i + 1024, numsurfaces);
10957                         texturenumsurfaces = 0;
10958                         texturesurfacelist[texturenumsurfaces++] = surface;
10959                         for (;j < endsurface;j++)
10960                         {
10961                                 surface = rsurface.modelsurfaces + surfacelist[j];
10962                                 if (texture != surface->texture)
10963                                         break;
10964                                 texturesurfacelist[texturenumsurfaces++] = surface;
10965                         }
10966                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10967                                 continue;
10968                         // render the range of surfaces as depth
10969                         if (!setup)
10970                         {
10971                                 setup = true;
10972                                 GL_ColorMask(0,0,0,0);
10973                                 GL_Color(1,1,1,1);
10974                                 GL_DepthTest(true);
10975                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10976                                 GL_DepthMask(true);
10977 //                              R_Mesh_ResetTextureState();
10978                         }
10979                         RSurf_SetupDepthAndCulling();
10980                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10981                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
10982                         if (rsurface.batchvertex3fbuffer)
10983                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10984                         else
10985                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10986                         RSurf_DrawBatch();
10987                 }
10988                 if (setup)
10989                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10990         }
10991
10992         for (i = 0;i < numsurfaces;i = j)
10993         {
10994                 j = i + 1;
10995                 surface = rsurface.modelsurfaces + surfacelist[i];
10996                 texture = surface->texture;
10997                 rsurface.texture = R_GetCurrentTexture(texture);
10998                 // scan ahead until we find a different texture
10999                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11000                 texturenumsurfaces = 0;
11001                 texturesurfacelist[texturenumsurfaces++] = surface;
11002                 if(FAKELIGHT_ENABLED)
11003                 {
11004                         rsurface.lightmaptexture = NULL;
11005                         rsurface.deluxemaptexture = NULL;
11006                         rsurface.uselightmaptexture = false;
11007                         for (;j < endsurface;j++)
11008                         {
11009                                 surface = rsurface.modelsurfaces + surfacelist[j];
11010                                 if (texture != surface->texture)
11011                                         break;
11012                                 texturesurfacelist[texturenumsurfaces++] = surface;
11013                         }
11014                 }
11015                 else
11016                 {
11017                         rsurface.lightmaptexture = surface->lightmaptexture;
11018                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11019                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11020                         for (;j < endsurface;j++)
11021                         {
11022                                 surface = rsurface.modelsurfaces + surfacelist[j];
11023                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11024                                         break;
11025                                 texturesurfacelist[texturenumsurfaces++] = surface;
11026                         }
11027                 }
11028                 // render the range of surfaces
11029                 if (ent == r_refdef.scene.worldentity)
11030                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11031                 else
11032                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11033         }
11034         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11035 }
11036
11037 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11038 {
11039         // transparent surfaces get pushed off into the transparent queue
11040         int surfacelistindex;
11041         const msurface_t *surface;
11042         vec3_t tempcenter, center;
11043         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11044         {
11045                 surface = texturesurfacelist[surfacelistindex];
11046                 if (r_transparent_sortsurfacesbynearest.integer)
11047                 {
11048                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11049                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11050                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11051                 }
11052                 else
11053                 {
11054                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11055                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11056                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11057                 }
11058                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11059                 if (rsurface.entity->transparent_offset) // transparent offset
11060                 {
11061                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11062                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11063                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11064                 }
11065                 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);
11066         }
11067 }
11068
11069 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11070 {
11071         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11072                 return;
11073         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11074                 return;
11075         RSurf_SetupDepthAndCulling();
11076         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11077         if (rsurface.batchvertex3fbuffer)
11078                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
11079         else
11080                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
11081         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11082         RSurf_DrawBatch();
11083 }
11084
11085 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11086 {
11087         CHECKGLERROR
11088         if (depthonly)
11089                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11090         else if (prepass)
11091         {
11092                 if (!rsurface.texture->currentnumlayers)
11093                         return;
11094                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11095                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11096                 else
11097                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11098         }
11099         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11100                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11101         else if (!rsurface.texture->currentnumlayers)
11102                 return;
11103         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11104         {
11105                 // in the deferred case, transparent surfaces were queued during prepass
11106                 if (!r_shadow_usingdeferredprepass)
11107                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11108         }
11109         else
11110         {
11111                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11112                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11113         }
11114         CHECKGLERROR
11115 }
11116
11117 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11118 {
11119         int i, j;
11120         texture_t *texture;
11121         R_FrameData_SetMark();
11122         // break the surface list down into batches by texture and use of lightmapping
11123         for (i = 0;i < numsurfaces;i = j)
11124         {
11125                 j = i + 1;
11126                 // texture is the base texture pointer, rsurface.texture is the
11127                 // current frame/skin the texture is directing us to use (for example
11128                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11129                 // use skin 1 instead)
11130                 texture = surfacelist[i]->texture;
11131                 rsurface.texture = R_GetCurrentTexture(texture);
11132                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11133                 {
11134                         // if this texture is not the kind we want, skip ahead to the next one
11135                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11136                                 ;
11137                         continue;
11138                 }
11139                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11140                 {
11141                         rsurface.lightmaptexture = NULL;
11142                         rsurface.deluxemaptexture = NULL;
11143                         rsurface.uselightmaptexture = false;
11144                         // simply scan ahead until we find a different texture or lightmap state
11145                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11146                                 ;
11147                 }
11148                 else
11149                 {
11150                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11151                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11152                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11153                         // simply scan ahead until we find a different texture or lightmap state
11154                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11155                                 ;
11156                 }
11157                 // render the range of surfaces
11158                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11159         }
11160         R_FrameData_ReturnToMark();
11161 }
11162
11163 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11164 {
11165         CHECKGLERROR
11166         if (depthonly)
11167                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11168         else if (prepass)
11169         {
11170                 if (!rsurface.texture->currentnumlayers)
11171                         return;
11172                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11173                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11174                 else
11175                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11176         }
11177         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11178                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11179         else if (!rsurface.texture->currentnumlayers)
11180                 return;
11181         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11182         {
11183                 // in the deferred case, transparent surfaces were queued during prepass
11184                 if (!r_shadow_usingdeferredprepass)
11185                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11186         }
11187         else
11188         {
11189                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11190                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11191         }
11192         CHECKGLERROR
11193 }
11194
11195 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11196 {
11197         int i, j;
11198         texture_t *texture;
11199         R_FrameData_SetMark();
11200         // break the surface list down into batches by texture and use of lightmapping
11201         for (i = 0;i < numsurfaces;i = j)
11202         {
11203                 j = i + 1;
11204                 // texture is the base texture pointer, rsurface.texture is the
11205                 // current frame/skin the texture is directing us to use (for example
11206                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11207                 // use skin 1 instead)
11208                 texture = surfacelist[i]->texture;
11209                 rsurface.texture = R_GetCurrentTexture(texture);
11210                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11211                 {
11212                         // if this texture is not the kind we want, skip ahead to the next one
11213                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11214                                 ;
11215                         continue;
11216                 }
11217                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11218                 {
11219                         rsurface.lightmaptexture = NULL;
11220                         rsurface.deluxemaptexture = NULL;
11221                         rsurface.uselightmaptexture = false;
11222                         // simply scan ahead until we find a different texture or lightmap state
11223                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11224                                 ;
11225                 }
11226                 else
11227                 {
11228                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11229                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11230                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11231                         // simply scan ahead until we find a different texture or lightmap state
11232                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11233                                 ;
11234                 }
11235                 // render the range of surfaces
11236                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11237         }
11238         R_FrameData_ReturnToMark();
11239 }
11240
11241 float locboxvertex3f[6*4*3] =
11242 {
11243         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11244         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11245         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11246         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11247         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11248         1,0,0, 0,0,0, 0,1,0, 1,1,0
11249 };
11250
11251 unsigned short locboxelements[6*2*3] =
11252 {
11253          0, 1, 2, 0, 2, 3,
11254          4, 5, 6, 4, 6, 7,
11255          8, 9,10, 8,10,11,
11256         12,13,14, 12,14,15,
11257         16,17,18, 16,18,19,
11258         20,21,22, 20,22,23
11259 };
11260
11261 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11262 {
11263         int i, j;
11264         cl_locnode_t *loc = (cl_locnode_t *)ent;
11265         vec3_t mins, size;
11266         float vertex3f[6*4*3];
11267         CHECKGLERROR
11268         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11269         GL_DepthMask(false);
11270         GL_DepthRange(0, 1);
11271         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11272         GL_DepthTest(true);
11273         GL_CullFace(GL_NONE);
11274         R_EntityMatrix(&identitymatrix);
11275
11276 //      R_Mesh_ResetTextureState();
11277
11278         i = surfacelist[0];
11279         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11280                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11281                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11282                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11283
11284         if (VectorCompare(loc->mins, loc->maxs))
11285         {
11286                 VectorSet(size, 2, 2, 2);
11287                 VectorMA(loc->mins, -0.5f, size, mins);
11288         }
11289         else
11290         {
11291                 VectorCopy(loc->mins, mins);
11292                 VectorSubtract(loc->maxs, loc->mins, size);
11293         }
11294
11295         for (i = 0;i < 6*4*3;)
11296                 for (j = 0;j < 3;j++, i++)
11297                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11298
11299         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11300         R_SetupShader_Generic_NoTexture(false, false);
11301         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11302 }
11303
11304 void R_DrawLocs(void)
11305 {
11306         int index;
11307         cl_locnode_t *loc, *nearestloc;
11308         vec3_t center;
11309         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11310         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11311         {
11312                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11313                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11314         }
11315 }
11316
11317 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11318 {
11319         if (decalsystem->decals)
11320                 Mem_Free(decalsystem->decals);
11321         memset(decalsystem, 0, sizeof(*decalsystem));
11322 }
11323
11324 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)
11325 {
11326         tridecal_t *decal;
11327         tridecal_t *decals;
11328         int i;
11329
11330         // expand or initialize the system
11331         if (decalsystem->maxdecals <= decalsystem->numdecals)
11332         {
11333                 decalsystem_t old = *decalsystem;
11334                 qboolean useshortelements;
11335                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11336                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11337                 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)));
11338                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11339                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11340                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11341                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11342                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11343                 if (decalsystem->numdecals)
11344                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11345                 if (old.decals)
11346                         Mem_Free(old.decals);
11347                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11348                         decalsystem->element3i[i] = i;
11349                 if (useshortelements)
11350                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11351                                 decalsystem->element3s[i] = i;
11352         }
11353
11354         // grab a decal and search for another free slot for the next one
11355         decals = decalsystem->decals;
11356         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11357         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11358                 ;
11359         decalsystem->freedecal = i;
11360         if (decalsystem->numdecals <= i)
11361                 decalsystem->numdecals = i + 1;
11362
11363         // initialize the decal
11364         decal->lived = 0;
11365         decal->triangleindex = triangleindex;
11366         decal->surfaceindex = surfaceindex;
11367         decal->decalsequence = decalsequence;
11368         decal->color4f[0][0] = c0[0];
11369         decal->color4f[0][1] = c0[1];
11370         decal->color4f[0][2] = c0[2];
11371         decal->color4f[0][3] = 1;
11372         decal->color4f[1][0] = c1[0];
11373         decal->color4f[1][1] = c1[1];
11374         decal->color4f[1][2] = c1[2];
11375         decal->color4f[1][3] = 1;
11376         decal->color4f[2][0] = c2[0];
11377         decal->color4f[2][1] = c2[1];
11378         decal->color4f[2][2] = c2[2];
11379         decal->color4f[2][3] = 1;
11380         decal->vertex3f[0][0] = v0[0];
11381         decal->vertex3f[0][1] = v0[1];
11382         decal->vertex3f[0][2] = v0[2];
11383         decal->vertex3f[1][0] = v1[0];
11384         decal->vertex3f[1][1] = v1[1];
11385         decal->vertex3f[1][2] = v1[2];
11386         decal->vertex3f[2][0] = v2[0];
11387         decal->vertex3f[2][1] = v2[1];
11388         decal->vertex3f[2][2] = v2[2];
11389         decal->texcoord2f[0][0] = t0[0];
11390         decal->texcoord2f[0][1] = t0[1];
11391         decal->texcoord2f[1][0] = t1[0];
11392         decal->texcoord2f[1][1] = t1[1];
11393         decal->texcoord2f[2][0] = t2[0];
11394         decal->texcoord2f[2][1] = t2[1];
11395         TriangleNormal(v0, v1, v2, decal->plane);
11396         VectorNormalize(decal->plane);
11397         decal->plane[3] = DotProduct(v0, decal->plane);
11398 }
11399
11400 extern cvar_t cl_decals_bias;
11401 extern cvar_t cl_decals_models;
11402 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11403 // baseparms, parms, temps
11404 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)
11405 {
11406         int cornerindex;
11407         int index;
11408         float v[9][3];
11409         const float *vertex3f;
11410         const float *normal3f;
11411         int numpoints;
11412         float points[2][9][3];
11413         float temp[3];
11414         float tc[9][2];
11415         float f;
11416         float c[9][4];
11417         const int *e;
11418
11419         e = rsurface.modelelement3i + 3*triangleindex;
11420
11421         vertex3f = rsurface.modelvertex3f;
11422         normal3f = rsurface.modelnormal3f;
11423
11424         if (normal3f)
11425         {
11426                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11427                 {
11428                         index = 3*e[cornerindex];
11429                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11430                 }
11431         }
11432         else
11433         {
11434                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11435                 {
11436                         index = 3*e[cornerindex];
11437                         VectorCopy(vertex3f + index, v[cornerindex]);
11438                 }
11439         }
11440
11441         // cull backfaces
11442         //TriangleNormal(v[0], v[1], v[2], normal);
11443         //if (DotProduct(normal, localnormal) < 0.0f)
11444         //      continue;
11445         // clip by each of the box planes formed from the projection matrix
11446         // if anything survives, we emit the decal
11447         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]);
11448         if (numpoints < 3)
11449                 return;
11450         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]);
11451         if (numpoints < 3)
11452                 return;
11453         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]);
11454         if (numpoints < 3)
11455                 return;
11456         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]);
11457         if (numpoints < 3)
11458                 return;
11459         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]);
11460         if (numpoints < 3)
11461                 return;
11462         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]);
11463         if (numpoints < 3)
11464                 return;
11465         // some part of the triangle survived, so we have to accept it...
11466         if (dynamic)
11467         {
11468                 // dynamic always uses the original triangle
11469                 numpoints = 3;
11470                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11471                 {
11472                         index = 3*e[cornerindex];
11473                         VectorCopy(vertex3f + index, v[cornerindex]);
11474                 }
11475         }
11476         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11477         {
11478                 // convert vertex positions to texcoords
11479                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11480                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11481                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11482                 // calculate distance fade from the projection origin
11483                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11484                 f = bound(0.0f, f, 1.0f);
11485                 c[cornerindex][0] = r * f;
11486                 c[cornerindex][1] = g * f;
11487                 c[cornerindex][2] = b * f;
11488                 c[cornerindex][3] = 1.0f;
11489                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11490         }
11491         if (dynamic)
11492                 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);
11493         else
11494                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11495                         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);
11496 }
11497 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)
11498 {
11499         matrix4x4_t projection;
11500         decalsystem_t *decalsystem;
11501         qboolean dynamic;
11502         dp_model_t *model;
11503         const msurface_t *surface;
11504         const msurface_t *surfaces;
11505         const int *surfacelist;
11506         const texture_t *texture;
11507         int numtriangles;
11508         int numsurfacelist;
11509         int surfacelistindex;
11510         int surfaceindex;
11511         int triangleindex;
11512         float localorigin[3];
11513         float localnormal[3];
11514         float localmins[3];
11515         float localmaxs[3];
11516         float localsize;
11517         //float normal[3];
11518         float planes[6][4];
11519         float angles[3];
11520         bih_t *bih;
11521         int bih_triangles_count;
11522         int bih_triangles[256];
11523         int bih_surfaces[256];
11524
11525         decalsystem = &ent->decalsystem;
11526         model = ent->model;
11527         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11528         {
11529                 R_DecalSystem_Reset(&ent->decalsystem);
11530                 return;
11531         }
11532
11533         if (!model->brush.data_leafs && !cl_decals_models.integer)
11534         {
11535                 if (decalsystem->model)
11536                         R_DecalSystem_Reset(decalsystem);
11537                 return;
11538         }
11539
11540         if (decalsystem->model != model)
11541                 R_DecalSystem_Reset(decalsystem);
11542         decalsystem->model = model;
11543
11544         RSurf_ActiveModelEntity(ent, true, false, false);
11545
11546         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11547         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11548         VectorNormalize(localnormal);
11549         localsize = worldsize*rsurface.inversematrixscale;
11550         localmins[0] = localorigin[0] - localsize;
11551         localmins[1] = localorigin[1] - localsize;
11552         localmins[2] = localorigin[2] - localsize;
11553         localmaxs[0] = localorigin[0] + localsize;
11554         localmaxs[1] = localorigin[1] + localsize;
11555         localmaxs[2] = localorigin[2] + localsize;
11556
11557         //VectorCopy(localnormal, planes[4]);
11558         //VectorVectors(planes[4], planes[2], planes[0]);
11559         AnglesFromVectors(angles, localnormal, NULL, false);
11560         AngleVectors(angles, planes[0], planes[2], planes[4]);
11561         VectorNegate(planes[0], planes[1]);
11562         VectorNegate(planes[2], planes[3]);
11563         VectorNegate(planes[4], planes[5]);
11564         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11565         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11566         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11567         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11568         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11569         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11570
11571 #if 1
11572 // works
11573 {
11574         matrix4x4_t forwardprojection;
11575         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11576         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11577 }
11578 #else
11579 // broken
11580 {
11581         float projectionvector[4][3];
11582         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11583         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11584         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11585         projectionvector[0][0] = planes[0][0] * ilocalsize;
11586         projectionvector[0][1] = planes[1][0] * ilocalsize;
11587         projectionvector[0][2] = planes[2][0] * ilocalsize;
11588         projectionvector[1][0] = planes[0][1] * ilocalsize;
11589         projectionvector[1][1] = planes[1][1] * ilocalsize;
11590         projectionvector[1][2] = planes[2][1] * ilocalsize;
11591         projectionvector[2][0] = planes[0][2] * ilocalsize;
11592         projectionvector[2][1] = planes[1][2] * ilocalsize;
11593         projectionvector[2][2] = planes[2][2] * ilocalsize;
11594         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11595         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11596         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11597         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11598 }
11599 #endif
11600
11601         dynamic = model->surfmesh.isanimated;
11602         numsurfacelist = model->nummodelsurfaces;
11603         surfacelist = model->sortedmodelsurfaces;
11604         surfaces = model->data_surfaces;
11605
11606         bih = NULL;
11607         bih_triangles_count = -1;
11608         if(!dynamic)
11609         {
11610                 if(model->render_bih.numleafs)
11611                         bih = &model->render_bih;
11612                 else if(model->collision_bih.numleafs)
11613                         bih = &model->collision_bih;
11614         }
11615         if(bih)
11616                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11617         if(bih_triangles_count == 0)
11618                 return;
11619         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11620                 return;
11621         if(bih_triangles_count > 0)
11622         {
11623                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11624                 {
11625                         surfaceindex = bih_surfaces[triangleindex];
11626                         surface = surfaces + surfaceindex;
11627                         texture = surface->texture;
11628                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11629                                 continue;
11630                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11631                                 continue;
11632                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11633                 }
11634         }
11635         else
11636         {
11637                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11638                 {
11639                         surfaceindex = surfacelist[surfacelistindex];
11640                         surface = surfaces + surfaceindex;
11641                         // check cull box first because it rejects more than any other check
11642                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11643                                 continue;
11644                         // skip transparent surfaces
11645                         texture = surface->texture;
11646                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11647                                 continue;
11648                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11649                                 continue;
11650                         numtriangles = surface->num_triangles;
11651                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11652                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11653                 }
11654         }
11655 }
11656
11657 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11658 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)
11659 {
11660         int renderentityindex;
11661         float worldmins[3];
11662         float worldmaxs[3];
11663         entity_render_t *ent;
11664
11665         if (!cl_decals_newsystem.integer)
11666                 return;
11667
11668         worldmins[0] = worldorigin[0] - worldsize;
11669         worldmins[1] = worldorigin[1] - worldsize;
11670         worldmins[2] = worldorigin[2] - worldsize;
11671         worldmaxs[0] = worldorigin[0] + worldsize;
11672         worldmaxs[1] = worldorigin[1] + worldsize;
11673         worldmaxs[2] = worldorigin[2] + worldsize;
11674
11675         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11676
11677         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11678         {
11679                 ent = r_refdef.scene.entities[renderentityindex];
11680                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11681                         continue;
11682
11683                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11684         }
11685 }
11686
11687 typedef struct r_decalsystem_splatqueue_s
11688 {
11689         vec3_t worldorigin;
11690         vec3_t worldnormal;
11691         float color[4];
11692         float tcrange[4];
11693         float worldsize;
11694         int decalsequence;
11695 }
11696 r_decalsystem_splatqueue_t;
11697
11698 int r_decalsystem_numqueued = 0;
11699 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11700
11701 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)
11702 {
11703         r_decalsystem_splatqueue_t *queue;
11704
11705         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11706                 return;
11707
11708         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11709         VectorCopy(worldorigin, queue->worldorigin);
11710         VectorCopy(worldnormal, queue->worldnormal);
11711         Vector4Set(queue->color, r, g, b, a);
11712         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11713         queue->worldsize = worldsize;
11714         queue->decalsequence = cl.decalsequence++;
11715 }
11716
11717 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11718 {
11719         int i;
11720         r_decalsystem_splatqueue_t *queue;
11721
11722         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11723                 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);
11724         r_decalsystem_numqueued = 0;
11725 }
11726
11727 extern cvar_t cl_decals_max;
11728 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11729 {
11730         int i;
11731         decalsystem_t *decalsystem = &ent->decalsystem;
11732         int numdecals;
11733         int killsequence;
11734         tridecal_t *decal;
11735         float frametime;
11736         float lifetime;
11737
11738         if (!decalsystem->numdecals)
11739                 return;
11740
11741         if (r_showsurfaces.integer)
11742                 return;
11743
11744         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11745         {
11746                 R_DecalSystem_Reset(decalsystem);
11747                 return;
11748         }
11749
11750         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11751         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11752
11753         if (decalsystem->lastupdatetime)
11754                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11755         else
11756                 frametime = 0;
11757         decalsystem->lastupdatetime = r_refdef.scene.time;
11758         numdecals = decalsystem->numdecals;
11759
11760         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11761         {
11762                 if (decal->color4f[0][3])
11763                 {
11764                         decal->lived += frametime;
11765                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11766                         {
11767                                 memset(decal, 0, sizeof(*decal));
11768                                 if (decalsystem->freedecal > i)
11769                                         decalsystem->freedecal = i;
11770                         }
11771                 }
11772         }
11773         decal = decalsystem->decals;
11774         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11775                 numdecals--;
11776
11777         // collapse the array by shuffling the tail decals into the gaps
11778         for (;;)
11779         {
11780                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11781                         decalsystem->freedecal++;
11782                 if (decalsystem->freedecal == numdecals)
11783                         break;
11784                 decal[decalsystem->freedecal] = decal[--numdecals];
11785         }
11786
11787         decalsystem->numdecals = numdecals;
11788
11789         if (numdecals <= 0)
11790         {
11791                 // if there are no decals left, reset decalsystem
11792                 R_DecalSystem_Reset(decalsystem);
11793         }
11794 }
11795
11796 extern skinframe_t *decalskinframe;
11797 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11798 {
11799         int i;
11800         decalsystem_t *decalsystem = &ent->decalsystem;
11801         int numdecals;
11802         tridecal_t *decal;
11803         float faderate;
11804         float alpha;
11805         float *v3f;
11806         float *c4f;
11807         float *t2f;
11808         const int *e;
11809         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11810         int numtris = 0;
11811
11812         numdecals = decalsystem->numdecals;
11813         if (!numdecals)
11814                 return;
11815
11816         if (r_showsurfaces.integer)
11817                 return;
11818
11819         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11820         {
11821                 R_DecalSystem_Reset(decalsystem);
11822                 return;
11823         }
11824
11825         // if the model is static it doesn't matter what value we give for
11826         // wantnormals and wanttangents, so this logic uses only rules applicable
11827         // to a model, knowing that they are meaningless otherwise
11828         if (ent == r_refdef.scene.worldentity)
11829                 RSurf_ActiveWorldEntity();
11830         else
11831                 RSurf_ActiveModelEntity(ent, false, false, false);
11832
11833         decalsystem->lastupdatetime = r_refdef.scene.time;
11834
11835         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11836
11837         // update vertex positions for animated models
11838         v3f = decalsystem->vertex3f;
11839         c4f = decalsystem->color4f;
11840         t2f = decalsystem->texcoord2f;
11841         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11842         {
11843                 if (!decal->color4f[0][3])
11844                         continue;
11845
11846                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11847                         continue;
11848
11849                 // skip backfaces
11850                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11851                         continue;
11852
11853                 // update color values for fading decals
11854                 if (decal->lived >= cl_decals_time.value)
11855                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11856                 else
11857                         alpha = 1.0f;
11858
11859                 c4f[ 0] = decal->color4f[0][0] * alpha;
11860                 c4f[ 1] = decal->color4f[0][1] * alpha;
11861                 c4f[ 2] = decal->color4f[0][2] * alpha;
11862                 c4f[ 3] = 1;
11863                 c4f[ 4] = decal->color4f[1][0] * alpha;
11864                 c4f[ 5] = decal->color4f[1][1] * alpha;
11865                 c4f[ 6] = decal->color4f[1][2] * alpha;
11866                 c4f[ 7] = 1;
11867                 c4f[ 8] = decal->color4f[2][0] * alpha;
11868                 c4f[ 9] = decal->color4f[2][1] * alpha;
11869                 c4f[10] = decal->color4f[2][2] * alpha;
11870                 c4f[11] = 1;
11871
11872                 t2f[0] = decal->texcoord2f[0][0];
11873                 t2f[1] = decal->texcoord2f[0][1];
11874                 t2f[2] = decal->texcoord2f[1][0];
11875                 t2f[3] = decal->texcoord2f[1][1];
11876                 t2f[4] = decal->texcoord2f[2][0];
11877                 t2f[5] = decal->texcoord2f[2][1];
11878
11879                 // update vertex positions for animated models
11880                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11881                 {
11882                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11883                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11884                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11885                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11886                 }
11887                 else
11888                 {
11889                         VectorCopy(decal->vertex3f[0], v3f);
11890                         VectorCopy(decal->vertex3f[1], v3f + 3);
11891                         VectorCopy(decal->vertex3f[2], v3f + 6);
11892                 }
11893
11894                 if (r_refdef.fogenabled)
11895                 {
11896                         alpha = RSurf_FogVertex(v3f);
11897                         VectorScale(c4f, alpha, c4f);
11898                         alpha = RSurf_FogVertex(v3f + 3);
11899                         VectorScale(c4f + 4, alpha, c4f + 4);
11900                         alpha = RSurf_FogVertex(v3f + 6);
11901                         VectorScale(c4f + 8, alpha, c4f + 8);
11902                 }
11903
11904                 v3f += 9;
11905                 c4f += 12;
11906                 t2f += 6;
11907                 numtris++;
11908         }
11909
11910         if (numtris > 0)
11911         {
11912                 r_refdef.stats[r_stat_drawndecals] += numtris;
11913
11914                 // now render the decals all at once
11915                 // (this assumes they all use one particle font texture!)
11916                 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);
11917 //              R_Mesh_ResetTextureState();
11918                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11919                 GL_DepthMask(false);
11920                 GL_DepthRange(0, 1);
11921                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11922                 GL_DepthTest(true);
11923                 GL_CullFace(GL_NONE);
11924                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11925                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11926                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11927         }
11928 }
11929
11930 static void R_DrawModelDecals(void)
11931 {
11932         int i, numdecals;
11933
11934         // fade faster when there are too many decals
11935         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11936         for (i = 0;i < r_refdef.scene.numentities;i++)
11937                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11938
11939         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11940         for (i = 0;i < r_refdef.scene.numentities;i++)
11941                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11942                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11943
11944         R_DecalSystem_ApplySplatEntitiesQueue();
11945
11946         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11947         for (i = 0;i < r_refdef.scene.numentities;i++)
11948                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11949
11950         r_refdef.stats[r_stat_totaldecals] += numdecals;
11951
11952         if (r_showsurfaces.integer)
11953                 return;
11954
11955         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11956
11957         for (i = 0;i < r_refdef.scene.numentities;i++)
11958         {
11959                 if (!r_refdef.viewcache.entityvisible[i])
11960                         continue;
11961                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11962                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11963         }
11964 }
11965
11966 extern cvar_t mod_collision_bih;
11967 static void R_DrawDebugModel(void)
11968 {
11969         entity_render_t *ent = rsurface.entity;
11970         int i, j, k, l, flagsmask;
11971         const msurface_t *surface;
11972         dp_model_t *model = ent->model;
11973         vec3_t v;
11974
11975         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11976                 return;
11977
11978         if (r_showoverdraw.value > 0)
11979         {
11980                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11981                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11982                 R_SetupShader_Generic_NoTexture(false, false);
11983                 GL_DepthTest(false);
11984                 GL_DepthMask(false);
11985                 GL_DepthRange(0, 1);
11986                 GL_BlendFunc(GL_ONE, GL_ONE);
11987                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11988                 {
11989                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11990                                 continue;
11991                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11992                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11993                         {
11994                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11995                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11996                                 if (!rsurface.texture->currentlayers->depthmask)
11997                                         GL_Color(c, 0, 0, 1.0f);
11998                                 else if (ent == r_refdef.scene.worldentity)
11999                                         GL_Color(c, c, c, 1.0f);
12000                                 else
12001                                         GL_Color(0, c, 0, 1.0f);
12002                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12003                                 RSurf_DrawBatch();
12004                         }
12005                 }
12006                 rsurface.texture = NULL;
12007         }
12008
12009         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12010
12011 //      R_Mesh_ResetTextureState();
12012         R_SetupShader_Generic_NoTexture(false, false);
12013         GL_DepthRange(0, 1);
12014         GL_DepthTest(!r_showdisabledepthtest.integer);
12015         GL_DepthMask(false);
12016         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12017
12018         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12019         {
12020                 int triangleindex;
12021                 int bihleafindex;
12022                 qboolean cullbox = false;
12023                 const q3mbrush_t *brush;
12024                 const bih_t *bih = &model->collision_bih;
12025                 const bih_leaf_t *bihleaf;
12026                 float vertex3f[3][3];
12027                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12028                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12029                 {
12030                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12031                                 continue;
12032                         switch (bihleaf->type)
12033                         {
12034                         case BIH_BRUSH:
12035                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12036                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12037                                 {
12038                                         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);
12039                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12040                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12041                                 }
12042                                 break;
12043                         case BIH_COLLISIONTRIANGLE:
12044                                 triangleindex = bihleaf->itemindex;
12045                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12046                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12047                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
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(3, vertex3f[0], NULL, NULL);
12050                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12051                                 break;
12052                         case BIH_RENDERTRIANGLE:
12053                                 triangleindex = bihleaf->itemindex;
12054                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12055                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12056                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12057                                 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);
12058                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12059                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12060                                 break;
12061                         }
12062                 }
12063         }
12064
12065         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12066
12067 #ifndef USE_GLES2
12068         if (r_showtris.integer && qglPolygonMode)
12069         {
12070                 if (r_showdisabledepthtest.integer)
12071                 {
12072                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12073                         GL_DepthMask(false);
12074                 }
12075                 else
12076                 {
12077                         GL_BlendFunc(GL_ONE, GL_ZERO);
12078                         GL_DepthMask(true);
12079                 }
12080                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12081                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12082                 {
12083                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12084                                 continue;
12085                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12086                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12087                         {
12088                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12089                                 if (!rsurface.texture->currentlayers->depthmask)
12090                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12091                                 else if (ent == r_refdef.scene.worldentity)
12092                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12093                                 else
12094                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12095                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12096                                 RSurf_DrawBatch();
12097                         }
12098                 }
12099                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12100                 rsurface.texture = NULL;
12101         }
12102
12103         if (r_shownormals.value != 0 && qglBegin)
12104         {
12105                 if (r_showdisabledepthtest.integer)
12106                 {
12107                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12108                         GL_DepthMask(false);
12109                 }
12110                 else
12111                 {
12112                         GL_BlendFunc(GL_ONE, GL_ZERO);
12113                         GL_DepthMask(true);
12114                 }
12115                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12116                 {
12117                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12118                                 continue;
12119                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12120                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12121                         {
12122                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12123                                 qglBegin(GL_LINES);
12124                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12125                                 {
12126                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12127                                         {
12128                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12129                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12130                                                 qglVertex3f(v[0], v[1], v[2]);
12131                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12132                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12133                                                 qglVertex3f(v[0], v[1], v[2]);
12134                                         }
12135                                 }
12136                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12137                                 {
12138                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12139                                         {
12140                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12141                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12142                                                 qglVertex3f(v[0], v[1], v[2]);
12143                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12144                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12145                                                 qglVertex3f(v[0], v[1], v[2]);
12146                                         }
12147                                 }
12148                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12149                                 {
12150                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12151                                         {
12152                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12153                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12154                                                 qglVertex3f(v[0], v[1], v[2]);
12155                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12156                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12157                                                 qglVertex3f(v[0], v[1], v[2]);
12158                                         }
12159                                 }
12160                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12161                                 {
12162                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12163                                         {
12164                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12165                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12166                                                 qglVertex3f(v[0], v[1], v[2]);
12167                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12168                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12169                                                 qglVertex3f(v[0], v[1], v[2]);
12170                                         }
12171                                 }
12172                                 qglEnd();
12173                                 CHECKGLERROR
12174                         }
12175                 }
12176                 rsurface.texture = NULL;
12177         }
12178 #endif
12179 }
12180
12181 int r_maxsurfacelist = 0;
12182 const msurface_t **r_surfacelist = NULL;
12183 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12184 {
12185         int i, j, endj, flagsmask;
12186         dp_model_t *model = r_refdef.scene.worldmodel;
12187         msurface_t *surfaces;
12188         unsigned char *update;
12189         int numsurfacelist = 0;
12190         if (model == NULL)
12191                 return;
12192
12193         if (r_maxsurfacelist < model->num_surfaces)
12194         {
12195                 r_maxsurfacelist = model->num_surfaces;
12196                 if (r_surfacelist)
12197                         Mem_Free((msurface_t**)r_surfacelist);
12198                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12199         }
12200
12201         RSurf_ActiveWorldEntity();
12202
12203         surfaces = model->data_surfaces;
12204         update = model->brushq1.lightmapupdateflags;
12205
12206         // update light styles on this submodel
12207         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12208         {
12209                 model_brush_lightstyleinfo_t *style;
12210                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12211                 {
12212                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12213                         {
12214                                 int *list = style->surfacelist;
12215                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12216                                 for (j = 0;j < style->numsurfaces;j++)
12217                                         update[list[j]] = true;
12218                         }
12219                 }
12220         }
12221
12222         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12223
12224         if (debug)
12225         {
12226                 R_DrawDebugModel();
12227                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12228                 return;
12229         }
12230
12231         rsurface.lightmaptexture = NULL;
12232         rsurface.deluxemaptexture = NULL;
12233         rsurface.uselightmaptexture = false;
12234         rsurface.texture = NULL;
12235         rsurface.rtlight = NULL;
12236         numsurfacelist = 0;
12237         // add visible surfaces to draw list
12238         for (i = 0;i < model->nummodelsurfaces;i++)
12239         {
12240                 j = model->sortedmodelsurfaces[i];
12241                 if (r_refdef.viewcache.world_surfacevisible[j])
12242                         r_surfacelist[numsurfacelist++] = surfaces + j;
12243         }
12244         // update lightmaps if needed
12245         if (model->brushq1.firstrender)
12246         {
12247                 model->brushq1.firstrender = false;
12248                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12249                         if (update[j])
12250                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12251         }
12252         else if (update)
12253         {
12254                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12255                         if (r_refdef.viewcache.world_surfacevisible[j])
12256                                 if (update[j])
12257                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12258         }
12259         // don't do anything if there were no surfaces
12260         if (!numsurfacelist)
12261         {
12262                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12263                 return;
12264         }
12265         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12266
12267         // add to stats if desired
12268         if (r_speeds.integer && !skysurfaces && !depthonly)
12269         {
12270                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12271                 for (j = 0;j < numsurfacelist;j++)
12272                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12273         }
12274
12275         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12276 }
12277
12278 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12279 {
12280         int i, j, endj, flagsmask;
12281         dp_model_t *model = ent->model;
12282         msurface_t *surfaces;
12283         unsigned char *update;
12284         int numsurfacelist = 0;
12285         if (model == NULL)
12286                 return;
12287
12288         if (r_maxsurfacelist < model->num_surfaces)
12289         {
12290                 r_maxsurfacelist = model->num_surfaces;
12291                 if (r_surfacelist)
12292                         Mem_Free((msurface_t **)r_surfacelist);
12293                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12294         }
12295
12296         // if the model is static it doesn't matter what value we give for
12297         // wantnormals and wanttangents, so this logic uses only rules applicable
12298         // to a model, knowing that they are meaningless otherwise
12299         if (ent == r_refdef.scene.worldentity)
12300                 RSurf_ActiveWorldEntity();
12301         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12302                 RSurf_ActiveModelEntity(ent, false, false, false);
12303         else if (prepass)
12304                 RSurf_ActiveModelEntity(ent, true, true, true);
12305         else if (depthonly)
12306         {
12307                 switch (vid.renderpath)
12308                 {
12309                 case RENDERPATH_GL20:
12310                 case RENDERPATH_D3D9:
12311                 case RENDERPATH_D3D10:
12312                 case RENDERPATH_D3D11:
12313                 case RENDERPATH_SOFT:
12314                 case RENDERPATH_GLES2:
12315                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12316                         break;
12317                 case RENDERPATH_GL11:
12318                 case RENDERPATH_GL13:
12319                 case RENDERPATH_GLES1:
12320                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12321                         break;
12322                 }
12323         }
12324         else
12325         {
12326                 switch (vid.renderpath)
12327                 {
12328                 case RENDERPATH_GL20:
12329                 case RENDERPATH_D3D9:
12330                 case RENDERPATH_D3D10:
12331                 case RENDERPATH_D3D11:
12332                 case RENDERPATH_SOFT:
12333                 case RENDERPATH_GLES2:
12334                         RSurf_ActiveModelEntity(ent, true, true, false);
12335                         break;
12336                 case RENDERPATH_GL11:
12337                 case RENDERPATH_GL13:
12338                 case RENDERPATH_GLES1:
12339                         RSurf_ActiveModelEntity(ent, true, false, false);
12340                         break;
12341                 }
12342         }
12343
12344         surfaces = model->data_surfaces;
12345         update = model->brushq1.lightmapupdateflags;
12346
12347         // update light styles
12348         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12349         {
12350                 model_brush_lightstyleinfo_t *style;
12351                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12352                 {
12353                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12354                         {
12355                                 int *list = style->surfacelist;
12356                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12357                                 for (j = 0;j < style->numsurfaces;j++)
12358                                         update[list[j]] = true;
12359                         }
12360                 }
12361         }
12362
12363         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12364
12365         if (debug)
12366         {
12367                 R_DrawDebugModel();
12368                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12369                 return;
12370         }
12371
12372         rsurface.lightmaptexture = NULL;
12373         rsurface.deluxemaptexture = NULL;
12374         rsurface.uselightmaptexture = false;
12375         rsurface.texture = NULL;
12376         rsurface.rtlight = NULL;
12377         numsurfacelist = 0;
12378         // add visible surfaces to draw list
12379         for (i = 0;i < model->nummodelsurfaces;i++)
12380                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12381         // don't do anything if there were no surfaces
12382         if (!numsurfacelist)
12383         {
12384                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12385                 return;
12386         }
12387         // update lightmaps if needed
12388         if (update)
12389         {
12390                 int updated = 0;
12391                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12392                 {
12393                         if (update[j])
12394                         {
12395                                 updated++;
12396                                 R_BuildLightMap(ent, surfaces + j);
12397                         }
12398                 }
12399         }
12400
12401         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12402
12403         // add to stats if desired
12404         if (r_speeds.integer && !skysurfaces && !depthonly)
12405         {
12406                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12407                 for (j = 0;j < numsurfacelist;j++)
12408                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12409         }
12410
12411         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12412 }
12413
12414 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12415 {
12416         static texture_t texture;
12417         static msurface_t surface;
12418         const msurface_t *surfacelist = &surface;
12419
12420         // fake enough texture and surface state to render this geometry
12421
12422         texture.update_lastrenderframe = -1; // regenerate this texture
12423         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12424         texture.currentskinframe = skinframe;
12425         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12426         texture.offsetmapping = OFFSETMAPPING_OFF;
12427         texture.offsetscale = 1;
12428         texture.specularscalemod = 1;
12429         texture.specularpowermod = 1;
12430         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12431         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12432         // JUST GREP FOR "specularscalemod = 1".
12433
12434         surface.texture = &texture;
12435         surface.num_triangles = numtriangles;
12436         surface.num_firsttriangle = firsttriangle;
12437         surface.num_vertices = numvertices;
12438         surface.num_firstvertex = firstvertex;
12439
12440         // now render it
12441         rsurface.texture = R_GetCurrentTexture(surface.texture);
12442         rsurface.lightmaptexture = NULL;
12443         rsurface.deluxemaptexture = NULL;
12444         rsurface.uselightmaptexture = false;
12445         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12446 }
12447
12448 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)
12449 {
12450         static msurface_t surface;
12451         const msurface_t *surfacelist = &surface;
12452
12453         // fake enough texture and surface state to render this geometry
12454         surface.texture = texture;
12455         surface.num_triangles = numtriangles;
12456         surface.num_firsttriangle = firsttriangle;
12457         surface.num_vertices = numvertices;
12458         surface.num_firstvertex = firstvertex;
12459
12460         // now render it
12461         rsurface.texture = R_GetCurrentTexture(surface.texture);
12462         rsurface.lightmaptexture = NULL;
12463         rsurface.deluxemaptexture = NULL;
12464         rsurface.uselightmaptexture = false;
12465         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12466 }