]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix a sizeof using an array index variable that is never initialized (harmless but...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
81 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
82 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
83 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
84 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
85 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
86 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
87 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
88 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
89 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
90 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
91 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
92 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
93 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
94 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
95 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
96 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
97 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
98 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
99 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
100 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
101 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
102 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
103 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
104 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
105 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
106 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
107
108 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
109 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
110 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
111
112 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
113 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
114 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
115 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
116 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
117 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
118 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
119 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
120 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
121 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
122 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
123 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
124 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
125 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
126 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
127 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
128 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
130 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
131 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
132 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
133 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
134 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
135 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
136 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
137 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
138
139 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
140 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
141 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
142 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
143 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
144 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
145 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
146 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
147
148 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
149 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
150
151 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
152 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
153 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
154
155 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
156 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
157 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
158 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
159 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
160 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
161 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
162 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
163 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
164
165 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
166 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
167 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
168 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
169 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
170 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
171 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
172 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
173 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
174 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
175 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
176 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
177 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
178 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
179 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
180 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
181 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
182 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
183 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
184
185 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
186 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
187 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
188 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
189 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
190 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
191 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
192 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
193 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
194
195 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
196 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
197 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
198 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
199
200 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
201 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
202
203 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
204 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
205 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
206 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
207 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
208 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
209
210 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
211 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
212 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
213 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
214 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
215 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
217 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
218 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
219 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
220
221 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
222
223 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
224
225 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
226
227 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
228
229 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
230 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
231 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
232
233 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
234 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
235
236 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
237
238 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
239
240 extern cvar_t v_glslgamma;
241 extern cvar_t v_glslgamma_2d;
242
243 extern qboolean v_flipped_state;
244
245 r_framebufferstate_t r_fb;
246
247 /// shadow volume bsp struct with automatically growing nodes buffer
248 svbsp_t r_svbsp;
249
250 rtexture_t *r_texture_blanknormalmap;
251 rtexture_t *r_texture_white;
252 rtexture_t *r_texture_grey128;
253 rtexture_t *r_texture_black;
254 rtexture_t *r_texture_notexture;
255 rtexture_t *r_texture_whitecube;
256 rtexture_t *r_texture_normalizationcube;
257 rtexture_t *r_texture_fogattenuation;
258 rtexture_t *r_texture_fogheighttexture;
259 rtexture_t *r_texture_gammaramps;
260 unsigned int r_texture_gammaramps_serial;
261 //rtexture_t *r_texture_fogintensity;
262 rtexture_t *r_texture_reflectcube;
263
264 // TODO: hash lookups?
265 typedef struct cubemapinfo_s
266 {
267         char basename[64];
268         rtexture_t *texture;
269 }
270 cubemapinfo_t;
271
272 int r_texture_numcubemaps;
273 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
274
275 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
276 unsigned int r_numqueries;
277 unsigned int r_maxqueries;
278
279 typedef struct r_qwskincache_s
280 {
281         char name[MAX_QPATH];
282         skinframe_t *skinframe;
283 }
284 r_qwskincache_t;
285
286 static r_qwskincache_t *r_qwskincache;
287 static int r_qwskincache_size;
288
289 /// vertex coordinates for a quad that covers the screen exactly
290 extern const float r_screenvertex3f[12];
291 extern const float r_d3dscreenvertex3f[12];
292 const float r_screenvertex3f[12] =
293 {
294         0, 0, 0,
295         1, 0, 0,
296         1, 1, 0,
297         0, 1, 0
298 };
299 const float r_d3dscreenvertex3f[12] =
300 {
301         0, 1, 0,
302         1, 1, 0,
303         1, 0, 0,
304         0, 0, 0
305 };
306
307 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
308 {
309         int i;
310         for (i = 0;i < verts;i++)
311         {
312                 out[0] = in[0] * r;
313                 out[1] = in[1] * g;
314                 out[2] = in[2] * b;
315                 out[3] = in[3];
316                 in += 4;
317                 out += 4;
318         }
319 }
320
321 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
322 {
323         int i;
324         for (i = 0;i < verts;i++)
325         {
326                 out[0] = r;
327                 out[1] = g;
328                 out[2] = b;
329                 out[3] = a;
330                 out += 4;
331         }
332 }
333
334 // FIXME: move this to client?
335 void FOG_clear(void)
336 {
337         if (gamemode == GAME_NEHAHRA)
338         {
339                 Cvar_Set("gl_fogenable", "0");
340                 Cvar_Set("gl_fogdensity", "0.2");
341                 Cvar_Set("gl_fogred", "0.3");
342                 Cvar_Set("gl_foggreen", "0.3");
343                 Cvar_Set("gl_fogblue", "0.3");
344         }
345         r_refdef.fog_density = 0;
346         r_refdef.fog_red = 0;
347         r_refdef.fog_green = 0;
348         r_refdef.fog_blue = 0;
349         r_refdef.fog_alpha = 1;
350         r_refdef.fog_start = 0;
351         r_refdef.fog_end = 16384;
352         r_refdef.fog_height = 1<<30;
353         r_refdef.fog_fadedepth = 128;
354         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
355 }
356
357 static void R_BuildBlankTextures(void)
358 {
359         unsigned char data[4];
360         data[2] = 128; // normal X
361         data[1] = 128; // normal Y
362         data[0] = 255; // normal Z
363         data[3] = 255; // height
364         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365         data[0] = 255;
366         data[1] = 255;
367         data[2] = 255;
368         data[3] = 255;
369         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370         data[0] = 128;
371         data[1] = 128;
372         data[2] = 128;
373         data[3] = 255;
374         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 0;
376         data[1] = 0;
377         data[2] = 0;
378         data[3] = 255;
379         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380 }
381
382 static void R_BuildNoTexture(void)
383 {
384         int x, y;
385         unsigned char pix[16][16][4];
386         // this makes a light grey/dark grey checkerboard texture
387         for (y = 0;y < 16;y++)
388         {
389                 for (x = 0;x < 16;x++)
390                 {
391                         if ((y < 8) ^ (x < 8))
392                         {
393                                 pix[y][x][0] = 128;
394                                 pix[y][x][1] = 128;
395                                 pix[y][x][2] = 128;
396                                 pix[y][x][3] = 255;
397                         }
398                         else
399                         {
400                                 pix[y][x][0] = 64;
401                                 pix[y][x][1] = 64;
402                                 pix[y][x][2] = 64;
403                                 pix[y][x][3] = 255;
404                         }
405                 }
406         }
407         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
408 }
409
410 static void R_BuildWhiteCube(void)
411 {
412         unsigned char data[6*1*1*4];
413         memset(data, 255, sizeof(data));
414         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
415 }
416
417 static void R_BuildNormalizationCube(void)
418 {
419         int x, y, side;
420         vec3_t v;
421         vec_t s, t, intensity;
422 #define NORMSIZE 64
423         unsigned char *data;
424         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
425         for (side = 0;side < 6;side++)
426         {
427                 for (y = 0;y < NORMSIZE;y++)
428                 {
429                         for (x = 0;x < NORMSIZE;x++)
430                         {
431                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
432                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
433                                 switch(side)
434                                 {
435                                 default:
436                                 case 0:
437                                         v[0] = 1;
438                                         v[1] = -t;
439                                         v[2] = -s;
440                                         break;
441                                 case 1:
442                                         v[0] = -1;
443                                         v[1] = -t;
444                                         v[2] = s;
445                                         break;
446                                 case 2:
447                                         v[0] = s;
448                                         v[1] = 1;
449                                         v[2] = t;
450                                         break;
451                                 case 3:
452                                         v[0] = s;
453                                         v[1] = -1;
454                                         v[2] = -t;
455                                         break;
456                                 case 4:
457                                         v[0] = s;
458                                         v[1] = -t;
459                                         v[2] = 1;
460                                         break;
461                                 case 5:
462                                         v[0] = -s;
463                                         v[1] = -t;
464                                         v[2] = -1;
465                                         break;
466                                 }
467                                 intensity = 127.0f / sqrt(DotProduct(v, v));
468                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
469                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
470                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
471                                 data[((side*64+y)*64+x)*4+3] = 255;
472                         }
473                 }
474         }
475         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
476         Mem_Free(data);
477 }
478
479 static void R_BuildFogTexture(void)
480 {
481         int x, b;
482 #define FOGWIDTH 256
483         unsigned char data1[FOGWIDTH][4];
484         //unsigned char data2[FOGWIDTH][4];
485         double d, r, alpha;
486
487         r_refdef.fogmasktable_start = r_refdef.fog_start;
488         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
489         r_refdef.fogmasktable_range = r_refdef.fogrange;
490         r_refdef.fogmasktable_density = r_refdef.fog_density;
491
492         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
493         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
494         {
495                 d = (x * r - r_refdef.fogmasktable_start);
496                 if(developer_extra.integer)
497                         Con_DPrintf("%f ", d);
498                 d = max(0, d);
499                 if (r_fog_exp2.integer)
500                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
501                 else
502                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
503                 if(developer_extra.integer)
504                         Con_DPrintf(" : %f ", alpha);
505                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
506                 if(developer_extra.integer)
507                         Con_DPrintf(" = %f\n", alpha);
508                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
509         }
510
511         for (x = 0;x < FOGWIDTH;x++)
512         {
513                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
514                 data1[x][0] = b;
515                 data1[x][1] = b;
516                 data1[x][2] = b;
517                 data1[x][3] = 255;
518                 //data2[x][0] = 255 - b;
519                 //data2[x][1] = 255 - b;
520                 //data2[x][2] = 255 - b;
521                 //data2[x][3] = 255;
522         }
523         if (r_texture_fogattenuation)
524         {
525                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
526                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
527         }
528         else
529         {
530                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
531                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
532         }
533 }
534
535 static void R_BuildFogHeightTexture(void)
536 {
537         unsigned char *inpixels;
538         int size;
539         int x;
540         int y;
541         int j;
542         float c[4];
543         float f;
544         inpixels = NULL;
545         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
546         if (r_refdef.fogheighttexturename[0])
547                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
548         if (!inpixels)
549         {
550                 r_refdef.fog_height_tablesize = 0;
551                 if (r_texture_fogheighttexture)
552                         R_FreeTexture(r_texture_fogheighttexture);
553                 r_texture_fogheighttexture = NULL;
554                 if (r_refdef.fog_height_table2d)
555                         Mem_Free(r_refdef.fog_height_table2d);
556                 r_refdef.fog_height_table2d = NULL;
557                 if (r_refdef.fog_height_table1d)
558                         Mem_Free(r_refdef.fog_height_table1d);
559                 r_refdef.fog_height_table1d = NULL;
560                 return;
561         }
562         size = image_width;
563         r_refdef.fog_height_tablesize = size;
564         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
565         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
566         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
567         Mem_Free(inpixels);
568         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
569         // average fog color table accounting for every fog layer between a point
570         // and the camera.  (Note: attenuation is handled separately!)
571         for (y = 0;y < size;y++)
572         {
573                 for (x = 0;x < size;x++)
574                 {
575                         Vector4Clear(c);
576                         f = 0;
577                         if (x < y)
578                         {
579                                 for (j = x;j <= y;j++)
580                                 {
581                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
582                                         f++;
583                                 }
584                         }
585                         else
586                         {
587                                 for (j = x;j >= y;j--)
588                                 {
589                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
590                                         f++;
591                                 }
592                         }
593                         f = 1.0f / f;
594                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
595                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
596                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
597                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
598                 }
599         }
600         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
601 }
602
603 //=======================================================================================================================================================
604
605 static const char *builtinshaderstrings[] =
606 {
607 #include "shader_glsl.h"
608 0
609 };
610
611 const char *builtinhlslshaderstrings[] =
612 {
613 #include "shader_hlsl.h"
614 0
615 };
616
617 char *glslshaderstring = NULL;
618 char *hlslshaderstring = NULL;
619
620 //=======================================================================================================================================================
621
622 typedef struct shaderpermutationinfo_s
623 {
624         const char *pretext;
625         const char *name;
626 }
627 shaderpermutationinfo_t;
628
629 typedef struct shadermodeinfo_s
630 {
631         const char *filename;
632         const char *pretext;
633         const char *name;
634 }
635 shadermodeinfo_t;
636
637 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
638 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
639 {
640         {"#define USEDIFFUSE\n", " diffuse"},
641         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
642         {"#define USEVIEWTINT\n", " viewtint"},
643         {"#define USECOLORMAPPING\n", " colormapping"},
644         {"#define USESATURATION\n", " saturation"},
645         {"#define USEFOGINSIDE\n", " foginside"},
646         {"#define USEFOGOUTSIDE\n", " fogoutside"},
647         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
648         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
649         {"#define USEGAMMARAMPS\n", " gammaramps"},
650         {"#define USECUBEFILTER\n", " cubefilter"},
651         {"#define USEGLOW\n", " glow"},
652         {"#define USEBLOOM\n", " bloom"},
653         {"#define USESPECULAR\n", " specular"},
654         {"#define USEPOSTPROCESSING\n", " postprocessing"},
655         {"#define USEREFLECTION\n", " reflection"},
656         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
657         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
658         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
659         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
660         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
661         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
662         {"#define USEALPHAKILL\n", " alphakill"},
663         {"#define USEREFLECTCUBE\n", " reflectcube"},
664         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
665         {"#define USEBOUNCEGRID\n", " bouncegrid"},
666         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
667         {"#define USETRIPPY\n", " trippy"},
668         {"#define USEDEPTHRGB\n", " depthrgb"},
669         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
670         {"#define USESKELETAL\n", " skeletal"}
671 };
672
673 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
674 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
675 {
676         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
677         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
678         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
679         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
680         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
681         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
682         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
683         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
684         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
685         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
686         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
687         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
688         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
689         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
690         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
691         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
692         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
693 };
694
695 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
696 {
697         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
698         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
699         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
700         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
701         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
702         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
703         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
704         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
705         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
706         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
707         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
708         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
709         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
710         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
711         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
712         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
713         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
714 };
715
716 struct r_glsl_permutation_s;
717 typedef struct r_glsl_permutation_s
718 {
719         /// hash lookup data
720         struct r_glsl_permutation_s *hashnext;
721         unsigned int mode;
722         unsigned int permutation;
723
724         /// indicates if we have tried compiling this permutation already
725         qboolean compiled;
726         /// 0 if compilation failed
727         int program;
728         // texture units assigned to each detected uniform
729         int tex_Texture_First;
730         int tex_Texture_Second;
731         int tex_Texture_GammaRamps;
732         int tex_Texture_Normal;
733         int tex_Texture_Color;
734         int tex_Texture_Gloss;
735         int tex_Texture_Glow;
736         int tex_Texture_SecondaryNormal;
737         int tex_Texture_SecondaryColor;
738         int tex_Texture_SecondaryGloss;
739         int tex_Texture_SecondaryGlow;
740         int tex_Texture_Pants;
741         int tex_Texture_Shirt;
742         int tex_Texture_FogHeightTexture;
743         int tex_Texture_FogMask;
744         int tex_Texture_Lightmap;
745         int tex_Texture_Deluxemap;
746         int tex_Texture_Attenuation;
747         int tex_Texture_Cube;
748         int tex_Texture_Refraction;
749         int tex_Texture_Reflection;
750         int tex_Texture_ShadowMap2D;
751         int tex_Texture_CubeProjection;
752         int tex_Texture_ScreenNormalMap;
753         int tex_Texture_ScreenDiffuse;
754         int tex_Texture_ScreenSpecular;
755         int tex_Texture_ReflectMask;
756         int tex_Texture_ReflectCube;
757         int tex_Texture_BounceGrid;
758         /// locations of detected uniforms in program object, or -1 if not found
759         int loc_Texture_First;
760         int loc_Texture_Second;
761         int loc_Texture_GammaRamps;
762         int loc_Texture_Normal;
763         int loc_Texture_Color;
764         int loc_Texture_Gloss;
765         int loc_Texture_Glow;
766         int loc_Texture_SecondaryNormal;
767         int loc_Texture_SecondaryColor;
768         int loc_Texture_SecondaryGloss;
769         int loc_Texture_SecondaryGlow;
770         int loc_Texture_Pants;
771         int loc_Texture_Shirt;
772         int loc_Texture_FogHeightTexture;
773         int loc_Texture_FogMask;
774         int loc_Texture_Lightmap;
775         int loc_Texture_Deluxemap;
776         int loc_Texture_Attenuation;
777         int loc_Texture_Cube;
778         int loc_Texture_Refraction;
779         int loc_Texture_Reflection;
780         int loc_Texture_ShadowMap2D;
781         int loc_Texture_CubeProjection;
782         int loc_Texture_ScreenNormalMap;
783         int loc_Texture_ScreenDiffuse;
784         int loc_Texture_ScreenSpecular;
785         int loc_Texture_ReflectMask;
786         int loc_Texture_ReflectCube;
787         int loc_Texture_BounceGrid;
788         int loc_Alpha;
789         int loc_BloomBlur_Parameters;
790         int loc_ClientTime;
791         int loc_Color_Ambient;
792         int loc_Color_Diffuse;
793         int loc_Color_Specular;
794         int loc_Color_Glow;
795         int loc_Color_Pants;
796         int loc_Color_Shirt;
797         int loc_DeferredColor_Ambient;
798         int loc_DeferredColor_Diffuse;
799         int loc_DeferredColor_Specular;
800         int loc_DeferredMod_Diffuse;
801         int loc_DeferredMod_Specular;
802         int loc_DistortScaleRefractReflect;
803         int loc_EyePosition;
804         int loc_FogColor;
805         int loc_FogHeightFade;
806         int loc_FogPlane;
807         int loc_FogPlaneViewDist;
808         int loc_FogRangeRecip;
809         int loc_LightColor;
810         int loc_LightDir;
811         int loc_LightPosition;
812         int loc_OffsetMapping_ScaleSteps;
813         int loc_OffsetMapping_LodDistance;
814         int loc_OffsetMapping_Bias;
815         int loc_PixelSize;
816         int loc_ReflectColor;
817         int loc_ReflectFactor;
818         int loc_ReflectOffset;
819         int loc_RefractColor;
820         int loc_Saturation;
821         int loc_ScreenCenterRefractReflect;
822         int loc_ScreenScaleRefractReflect;
823         int loc_ScreenToDepth;
824         int loc_ShadowMap_Parameters;
825         int loc_ShadowMap_TextureScale;
826         int loc_SpecularPower;
827         int loc_Skeletal_Transform12;
828         int loc_UserVec1;
829         int loc_UserVec2;
830         int loc_UserVec3;
831         int loc_UserVec4;
832         int loc_ViewTintColor;
833         int loc_ViewToLight;
834         int loc_ModelToLight;
835         int loc_TexMatrix;
836         int loc_BackgroundTexMatrix;
837         int loc_ModelViewProjectionMatrix;
838         int loc_ModelViewMatrix;
839         int loc_PixelToScreenTexCoord;
840         int loc_ModelToReflectCube;
841         int loc_ShadowMapMatrix;
842         int loc_BloomColorSubtract;
843         int loc_NormalmapScrollBlend;
844         int loc_BounceGridMatrix;
845         int loc_BounceGridIntensity;
846 }
847 r_glsl_permutation_t;
848
849 #define SHADERPERMUTATION_HASHSIZE 256
850
851
852 // non-degradable "lightweight" shader parameters to keep the permutations simpler
853 // these can NOT degrade! only use for simple stuff
854 enum
855 {
856         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
857         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
858         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
859         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
861         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
862         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
863         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
864         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
865         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
866         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
867         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
868         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
869 };
870 #define SHADERSTATICPARMS_COUNT 13
871
872 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
873 static int shaderstaticparms_count = 0;
874
875 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
876 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
877
878 extern qboolean r_shadow_shadowmapsampler;
879 extern int r_shadow_shadowmappcf;
880 qboolean R_CompileShader_CheckStaticParms(void)
881 {
882         static int r_compileshader_staticparms_save[1];
883         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
884         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
885
886         // detect all
887         if (r_glsl_saturation_redcompensate.integer)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
889         if (r_glsl_vertextextureblend_usebothalphas.integer)
890                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
891         if (r_shadow_glossexact.integer)
892                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
893         if (r_glsl_postprocess.integer)
894         {
895                 if (r_glsl_postprocess_uservec1_enable.integer)
896                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
897                 if (r_glsl_postprocess_uservec2_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
899                 if (r_glsl_postprocess_uservec3_enable.integer)
900                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
901                 if (r_glsl_postprocess_uservec4_enable.integer)
902                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
903         }
904         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
906
907         if (r_shadow_shadowmapsampler)
908                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
909         if (r_shadow_shadowmappcf > 1)
910                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
911         else if (r_shadow_shadowmappcf)
912                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
913         if (r_celshading.integer)
914                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
915         if (r_celoutlines.integer)
916                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
917
918         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
919 }
920
921 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
922         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
923                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
924         else \
925                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
926 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
927 {
928         shaderstaticparms_count = 0;
929
930         // emit all
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
936         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
937         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
938         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
939         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
940         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
941         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
942         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
943         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
944 }
945
946 /// information about each possible shader permutation
947 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
948 /// currently selected permutation
949 r_glsl_permutation_t *r_glsl_permutation;
950 /// storage for permutations linked in the hash table
951 memexpandablearray_t r_glsl_permutationarray;
952
953 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
954 {
955         //unsigned int hashdepth = 0;
956         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
957         r_glsl_permutation_t *p;
958         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
959         {
960                 if (p->mode == mode && p->permutation == permutation)
961                 {
962                         //if (hashdepth > 10)
963                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
964                         return p;
965                 }
966                 //hashdepth++;
967         }
968         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
969         p->mode = mode;
970         p->permutation = permutation;
971         p->hashnext = r_glsl_permutationhash[mode][hashindex];
972         r_glsl_permutationhash[mode][hashindex] = p;
973         //if (hashdepth > 10)
974         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
975         return p;
976 }
977
978 static char *R_ShaderStrCat(const char **strings)
979 {
980         char *string, *s;
981         const char **p = strings;
982         const char *t;
983         size_t len = 0;
984         for (p = strings;(t = *p);p++)
985                 len += strlen(t);
986         len++;
987         s = string = (char *)Mem_Alloc(r_main_mempool, len);
988         len = 0;
989         for (p = strings;(t = *p);p++)
990         {
991                 len = strlen(t);
992                 memcpy(s, t, len);
993                 s += len;
994         }
995         *s = 0;
996         return string;
997 }
998
999 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1000 {
1001         char *shaderstring;
1002         if (!filename || !filename[0])
1003                 return NULL;
1004         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1005         if (!strcmp(filename, "glsl/default.glsl"))
1006         {
1007                 if (builtinonly)
1008                         return R_ShaderStrCat(builtinshaderstrings);
1009                 if (!glslshaderstring)
1010                 {
1011                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1012                         if (glslshaderstring)
1013                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1014                         else
1015                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1016                 }
1017                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1018                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1019                 return shaderstring;
1020         }
1021         if (!strcmp(filename, "hlsl/default.hlsl"))
1022         {
1023                 if (builtinonly)
1024                         return R_ShaderStrCat(builtinhlslshaderstrings);
1025                 if (!hlslshaderstring)
1026                 {
1027                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1028                         if (hlslshaderstring)
1029                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1030                         else
1031                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1032                 }
1033                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1034                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1035                 return shaderstring;
1036         }
1037         // we don't have builtin strings for any other files
1038         if (builtinonly)
1039                 return NULL;
1040         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1041         if (shaderstring)
1042         {
1043                 if (printfromdisknotice)
1044                         Con_DPrintf("from disk %s... ", filename);
1045                 return shaderstring;
1046         }
1047         return shaderstring;
1048 }
1049
1050 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1051 {
1052         int i;
1053         int sampler;
1054         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1055         char *sourcestring;
1056         char permutationname[256];
1057         int vertstrings_count = 0;
1058         int geomstrings_count = 0;
1059         int fragstrings_count = 0;
1060         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1061         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1062         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1063
1064         if (p->compiled)
1065                 return;
1066         p->compiled = true;
1067         p->program = 0;
1068
1069         permutationname[0] = 0;
1070         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1071
1072         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1073
1074         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1075         if(vid.support.gl20shaders130)
1076         {
1077                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1078                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1079                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1080                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1081                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1082                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1083         }
1084
1085         // the first pretext is which type of shader to compile as
1086         // (later these will all be bound together as a program object)
1087         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1088         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1089         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1090
1091         // the second pretext is the mode (for example a light source)
1092         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1093         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1094         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1095         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1096
1097         // now add all the permutation pretexts
1098         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1099         {
1100                 if (permutation & (1<<i))
1101                 {
1102                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1103                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1104                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1105                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1106                 }
1107                 else
1108                 {
1109                         // keep line numbers correct
1110                         vertstrings_list[vertstrings_count++] = "\n";
1111                         geomstrings_list[geomstrings_count++] = "\n";
1112                         fragstrings_list[fragstrings_count++] = "\n";
1113                 }
1114         }
1115
1116         // add static parms
1117         R_CompileShader_AddStaticParms(mode, permutation);
1118         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1119         vertstrings_count += shaderstaticparms_count;
1120         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1121         geomstrings_count += shaderstaticparms_count;
1122         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1123         fragstrings_count += shaderstaticparms_count;
1124
1125         // now append the shader text itself
1126         vertstrings_list[vertstrings_count++] = sourcestring;
1127         geomstrings_list[geomstrings_count++] = sourcestring;
1128         fragstrings_list[fragstrings_count++] = sourcestring;
1129
1130         // compile the shader program
1131         if (vertstrings_count + geomstrings_count + fragstrings_count)
1132                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1133         if (p->program)
1134         {
1135                 CHECKGLERROR
1136                 qglUseProgram(p->program);CHECKGLERROR
1137                 // look up all the uniform variable names we care about, so we don't
1138                 // have to look them up every time we set them
1139
1140                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1141                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1142                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1143                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1144                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1145                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1146                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1147                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1148                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1149                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1150                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1151                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1152                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1153                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1154                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1155                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1156                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1157                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1158                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1159                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1160                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1161                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1162                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1163                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1164                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1165                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1166                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1167                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1168                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1169                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1170                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1171                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1172                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1173                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1174                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1175                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1176                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1177                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1178                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1179                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1180                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1181                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1182                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1183                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1184                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1185                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1186                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1187                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1188                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1189                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1190                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1191                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1192                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1193                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1194                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1195                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1196                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1197                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1198                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1199                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1200                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1201                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1202                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1203                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1204                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1205                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1206                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1207                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1208                 p->loc_Skeletal_Transform12       = qglGetUniformLocation(p->program, "Skeletal_Transform12");
1209                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1210                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1211                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1212                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1213                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1214                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1215                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1216                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1217                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1218                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1219                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1220                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1221                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1222                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1223                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1224                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1225                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1226                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1227                 // initialize the samplers to refer to the texture units we use
1228                 p->tex_Texture_First = -1;
1229                 p->tex_Texture_Second = -1;
1230                 p->tex_Texture_GammaRamps = -1;
1231                 p->tex_Texture_Normal = -1;
1232                 p->tex_Texture_Color = -1;
1233                 p->tex_Texture_Gloss = -1;
1234                 p->tex_Texture_Glow = -1;
1235                 p->tex_Texture_SecondaryNormal = -1;
1236                 p->tex_Texture_SecondaryColor = -1;
1237                 p->tex_Texture_SecondaryGloss = -1;
1238                 p->tex_Texture_SecondaryGlow = -1;
1239                 p->tex_Texture_Pants = -1;
1240                 p->tex_Texture_Shirt = -1;
1241                 p->tex_Texture_FogHeightTexture = -1;
1242                 p->tex_Texture_FogMask = -1;
1243                 p->tex_Texture_Lightmap = -1;
1244                 p->tex_Texture_Deluxemap = -1;
1245                 p->tex_Texture_Attenuation = -1;
1246                 p->tex_Texture_Cube = -1;
1247                 p->tex_Texture_Refraction = -1;
1248                 p->tex_Texture_Reflection = -1;
1249                 p->tex_Texture_ShadowMap2D = -1;
1250                 p->tex_Texture_CubeProjection = -1;
1251                 p->tex_Texture_ScreenNormalMap = -1;
1252                 p->tex_Texture_ScreenDiffuse = -1;
1253                 p->tex_Texture_ScreenSpecular = -1;
1254                 p->tex_Texture_ReflectMask = -1;
1255                 p->tex_Texture_ReflectCube = -1;
1256                 p->tex_Texture_BounceGrid = -1;
1257                 sampler = 0;
1258                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1259                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1260                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1261                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1262                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1263                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1264                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1265                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1266                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1267                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1268                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1269                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1270                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1271                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1272                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1273                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1274                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1275                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1276                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1277                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1278                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1279                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1280                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1281                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1282                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1283                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1284                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1285                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1286                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1287                 CHECKGLERROR
1288                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1289         }
1290         else
1291                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1292
1293         // free the strings
1294         if (sourcestring)
1295                 Mem_Free(sourcestring);
1296 }
1297
1298 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1299 {
1300         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1301         if (r_glsl_permutation != perm)
1302         {
1303                 r_glsl_permutation = perm;
1304                 if (!r_glsl_permutation->program)
1305                 {
1306                         if (!r_glsl_permutation->compiled)
1307                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1308                         if (!r_glsl_permutation->program)
1309                         {
1310                                 // remove features until we find a valid permutation
1311                                 int i;
1312                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1313                                 {
1314                                         // reduce i more quickly whenever it would not remove any bits
1315                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1316                                         if (!(permutation & j))
1317                                                 continue;
1318                                         permutation -= j;
1319                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1320                                         if (!r_glsl_permutation->compiled)
1321                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1322                                         if (r_glsl_permutation->program)
1323                                                 break;
1324                                 }
1325                                 if (i >= SHADERPERMUTATION_COUNT)
1326                                 {
1327                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1328                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1329                                         qglUseProgram(0);CHECKGLERROR
1330                                         return; // no bit left to clear, entire mode is broken
1331                                 }
1332                         }
1333                 }
1334                 CHECKGLERROR
1335                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1336         }
1337         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1338         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1339         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1340 }
1341
1342 #ifdef SUPPORTD3D
1343
1344 #ifdef SUPPORTD3D
1345 #include <d3d9.h>
1346 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1347 extern D3DCAPS9 vid_d3d9caps;
1348 #endif
1349
1350 struct r_hlsl_permutation_s;
1351 typedef struct r_hlsl_permutation_s
1352 {
1353         /// hash lookup data
1354         struct r_hlsl_permutation_s *hashnext;
1355         unsigned int mode;
1356         unsigned int permutation;
1357
1358         /// indicates if we have tried compiling this permutation already
1359         qboolean compiled;
1360         /// NULL if compilation failed
1361         IDirect3DVertexShader9 *vertexshader;
1362         IDirect3DPixelShader9 *pixelshader;
1363 }
1364 r_hlsl_permutation_t;
1365
1366 typedef enum D3DVSREGISTER_e
1367 {
1368         D3DVSREGISTER_TexMatrix = 0, // float4x4
1369         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1370         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1371         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1372         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1373         D3DVSREGISTER_ModelToLight = 20, // float4x4
1374         D3DVSREGISTER_EyePosition = 24,
1375         D3DVSREGISTER_FogPlane = 25,
1376         D3DVSREGISTER_LightDir = 26,
1377         D3DVSREGISTER_LightPosition = 27,
1378 }
1379 D3DVSREGISTER_t;
1380
1381 typedef enum D3DPSREGISTER_e
1382 {
1383         D3DPSREGISTER_Alpha = 0,
1384         D3DPSREGISTER_BloomBlur_Parameters = 1,
1385         D3DPSREGISTER_ClientTime = 2,
1386         D3DPSREGISTER_Color_Ambient = 3,
1387         D3DPSREGISTER_Color_Diffuse = 4,
1388         D3DPSREGISTER_Color_Specular = 5,
1389         D3DPSREGISTER_Color_Glow = 6,
1390         D3DPSREGISTER_Color_Pants = 7,
1391         D3DPSREGISTER_Color_Shirt = 8,
1392         D3DPSREGISTER_DeferredColor_Ambient = 9,
1393         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1394         D3DPSREGISTER_DeferredColor_Specular = 11,
1395         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1396         D3DPSREGISTER_DeferredMod_Specular = 13,
1397         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1398         D3DPSREGISTER_EyePosition = 15, // unused
1399         D3DPSREGISTER_FogColor = 16,
1400         D3DPSREGISTER_FogHeightFade = 17,
1401         D3DPSREGISTER_FogPlane = 18,
1402         D3DPSREGISTER_FogPlaneViewDist = 19,
1403         D3DPSREGISTER_FogRangeRecip = 20,
1404         D3DPSREGISTER_LightColor = 21,
1405         D3DPSREGISTER_LightDir = 22, // unused
1406         D3DPSREGISTER_LightPosition = 23,
1407         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1408         D3DPSREGISTER_PixelSize = 25,
1409         D3DPSREGISTER_ReflectColor = 26,
1410         D3DPSREGISTER_ReflectFactor = 27,
1411         D3DPSREGISTER_ReflectOffset = 28,
1412         D3DPSREGISTER_RefractColor = 29,
1413         D3DPSREGISTER_Saturation = 30,
1414         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1415         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1416         D3DPSREGISTER_ScreenToDepth = 33,
1417         D3DPSREGISTER_ShadowMap_Parameters = 34,
1418         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1419         D3DPSREGISTER_SpecularPower = 36,
1420         D3DPSREGISTER_UserVec1 = 37,
1421         D3DPSREGISTER_UserVec2 = 38,
1422         D3DPSREGISTER_UserVec3 = 39,
1423         D3DPSREGISTER_UserVec4 = 40,
1424         D3DPSREGISTER_ViewTintColor = 41,
1425         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1426         D3DPSREGISTER_BloomColorSubtract = 43,
1427         D3DPSREGISTER_ViewToLight = 44, // float4x4
1428         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1429         D3DPSREGISTER_NormalmapScrollBlend = 52,
1430         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1431         D3DPSREGISTER_OffsetMapping_Bias = 54,
1432         // next at 54
1433 }
1434 D3DPSREGISTER_t;
1435
1436 /// information about each possible shader permutation
1437 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1438 /// currently selected permutation
1439 r_hlsl_permutation_t *r_hlsl_permutation;
1440 /// storage for permutations linked in the hash table
1441 memexpandablearray_t r_hlsl_permutationarray;
1442
1443 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1444 {
1445         //unsigned int hashdepth = 0;
1446         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1447         r_hlsl_permutation_t *p;
1448         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1449         {
1450                 if (p->mode == mode && p->permutation == permutation)
1451                 {
1452                         //if (hashdepth > 10)
1453                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1454                         return p;
1455                 }
1456                 //hashdepth++;
1457         }
1458         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1459         p->mode = mode;
1460         p->permutation = permutation;
1461         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1462         r_hlsl_permutationhash[mode][hashindex] = p;
1463         //if (hashdepth > 10)
1464         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1465         return p;
1466 }
1467
1468 #include <d3dx9.h>
1469 //#include <d3dx9shader.h>
1470 //#include <d3dx9mesh.h>
1471
1472 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1473 {
1474         DWORD *vsbin = NULL;
1475         DWORD *psbin = NULL;
1476         fs_offset_t vsbinsize;
1477         fs_offset_t psbinsize;
1478 //      IDirect3DVertexShader9 *vs = NULL;
1479 //      IDirect3DPixelShader9 *ps = NULL;
1480         ID3DXBuffer *vslog = NULL;
1481         ID3DXBuffer *vsbuffer = NULL;
1482         ID3DXConstantTable *vsconstanttable = NULL;
1483         ID3DXBuffer *pslog = NULL;
1484         ID3DXBuffer *psbuffer = NULL;
1485         ID3DXConstantTable *psconstanttable = NULL;
1486         int vsresult = 0;
1487         int psresult = 0;
1488         char temp[MAX_INPUTLINE];
1489         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1490         char vabuf[1024];
1491         qboolean debugshader = gl_paranoid.integer != 0;
1492         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1493         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1494         if (!debugshader)
1495         {
1496                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1497                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1498         }
1499         if ((!vsbin && vertstring) || (!psbin && fragstring))
1500         {
1501                 const char* dllnames_d3dx9 [] =
1502                 {
1503                         "d3dx9_43.dll",
1504                         "d3dx9_42.dll",
1505                         "d3dx9_41.dll",
1506                         "d3dx9_40.dll",
1507                         "d3dx9_39.dll",
1508                         "d3dx9_38.dll",
1509                         "d3dx9_37.dll",
1510                         "d3dx9_36.dll",
1511                         "d3dx9_35.dll",
1512                         "d3dx9_34.dll",
1513                         "d3dx9_33.dll",
1514                         "d3dx9_32.dll",
1515                         "d3dx9_31.dll",
1516                         "d3dx9_30.dll",
1517                         "d3dx9_29.dll",
1518                         "d3dx9_28.dll",
1519                         "d3dx9_27.dll",
1520                         "d3dx9_26.dll",
1521                         "d3dx9_25.dll",
1522                         "d3dx9_24.dll",
1523                         NULL
1524                 };
1525                 dllhandle_t d3dx9_dll = NULL;
1526                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1527                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1528                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1529                 dllfunction_t d3dx9_dllfuncs[] =
1530                 {
1531                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1532                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1533                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1534                         {NULL, NULL}
1535                 };
1536                 // LordHavoc: the June 2010 SDK lacks these macros to make ID3DXBuffer usable in C, and to make it work in both C and C++ the macros are needed...
1537 #ifndef ID3DXBuffer_GetBufferPointer
1538 #if !defined(__cplusplus) || defined(CINTERFACE)
1539 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1540 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1541 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1542 #else
1543 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1544 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1545 #define ID3DXBuffer_Release(p)            (p)->Release()
1546 #endif
1547 #endif
1548                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1549                 {
1550                         DWORD shaderflags = 0;
1551                         if (debugshader)
1552                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1553                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1554                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1555                         if (vertstring && vertstring[0])
1556                         {
1557                                 if (debugshader)
1558                                 {
1559                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1560                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1561                                 }
1562                                 else
1563                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1564                                 if (vsbuffer)
1565                                 {
1566                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1567                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1568                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1569                                         ID3DXBuffer_Release(vsbuffer);
1570                                 }
1571                                 if (vslog)
1572                                 {
1573                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1574                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1575                                         ID3DXBuffer_Release(vslog);
1576                                 }
1577                         }
1578                         if (fragstring && fragstring[0])
1579                         {
1580                                 if (debugshader)
1581                                 {
1582                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1583                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1584                                 }
1585                                 else
1586                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1587                                 if (psbuffer)
1588                                 {
1589                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1590                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1591                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1592                                         ID3DXBuffer_Release(psbuffer);
1593                                 }
1594                                 if (pslog)
1595                                 {
1596                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1597                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1598                                         ID3DXBuffer_Release(pslog);
1599                                 }
1600                         }
1601                         Sys_UnloadLibrary(&d3dx9_dll);
1602                 }
1603                 else
1604                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1605         }
1606         if (vsbin && psbin)
1607         {
1608                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1609                 if (FAILED(vsresult))
1610                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1611                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1612                 if (FAILED(psresult))
1613                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1614         }
1615         // free the shader data
1616         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1617         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1618 }
1619
1620 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1621 {
1622         int i;
1623         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1624         int vertstring_length = 0;
1625         int geomstring_length = 0;
1626         int fragstring_length = 0;
1627         char *t;
1628         char *sourcestring;
1629         char *vertstring, *geomstring, *fragstring;
1630         char permutationname[256];
1631         char cachename[256];
1632         int vertstrings_count = 0;
1633         int geomstrings_count = 0;
1634         int fragstrings_count = 0;
1635         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1636         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1637         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1638
1639         if (p->compiled)
1640                 return;
1641         p->compiled = true;
1642         p->vertexshader = NULL;
1643         p->pixelshader = NULL;
1644
1645         permutationname[0] = 0;
1646         cachename[0] = 0;
1647         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1648
1649         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1650         strlcat(cachename, "hlsl/", sizeof(cachename));
1651
1652         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1653         vertstrings_count = 0;
1654         geomstrings_count = 0;
1655         fragstrings_count = 0;
1656         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1657         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1658         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1659
1660         // the first pretext is which type of shader to compile as
1661         // (later these will all be bound together as a program object)
1662         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1663         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1664         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1665
1666         // the second pretext is the mode (for example a light source)
1667         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1668         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1669         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1670         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1671         strlcat(cachename, modeinfo->name, sizeof(cachename));
1672
1673         // now add all the permutation pretexts
1674         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1675         {
1676                 if (permutation & (1<<i))
1677                 {
1678                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1679                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1680                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1681                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1682                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1683                 }
1684                 else
1685                 {
1686                         // keep line numbers correct
1687                         vertstrings_list[vertstrings_count++] = "\n";
1688                         geomstrings_list[geomstrings_count++] = "\n";
1689                         fragstrings_list[fragstrings_count++] = "\n";
1690                 }
1691         }
1692
1693         // add static parms
1694         R_CompileShader_AddStaticParms(mode, permutation);
1695         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1696         vertstrings_count += shaderstaticparms_count;
1697         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1698         geomstrings_count += shaderstaticparms_count;
1699         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1700         fragstrings_count += shaderstaticparms_count;
1701
1702         // replace spaces in the cachename with _ characters
1703         for (i = 0;cachename[i];i++)
1704                 if (cachename[i] == ' ')
1705                         cachename[i] = '_';
1706
1707         // now append the shader text itself
1708         vertstrings_list[vertstrings_count++] = sourcestring;
1709         geomstrings_list[geomstrings_count++] = sourcestring;
1710         fragstrings_list[fragstrings_count++] = sourcestring;
1711
1712         vertstring_length = 0;
1713         for (i = 0;i < vertstrings_count;i++)
1714                 vertstring_length += strlen(vertstrings_list[i]);
1715         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1716         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1717                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1718
1719         geomstring_length = 0;
1720         for (i = 0;i < geomstrings_count;i++)
1721                 geomstring_length += strlen(geomstrings_list[i]);
1722         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1723         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1724                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1725
1726         fragstring_length = 0;
1727         for (i = 0;i < fragstrings_count;i++)
1728                 fragstring_length += strlen(fragstrings_list[i]);
1729         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1730         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1731                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1732
1733         // try to load the cached shader, or generate one
1734         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1735
1736         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1737                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1738         else
1739                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1740
1741         // free the strings
1742         if (vertstring)
1743                 Mem_Free(vertstring);
1744         if (geomstring)
1745                 Mem_Free(geomstring);
1746         if (fragstring)
1747                 Mem_Free(fragstring);
1748         if (sourcestring)
1749                 Mem_Free(sourcestring);
1750 }
1751
1752 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1753 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1754 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1755 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1756 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1757 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1758
1759 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1760 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1761 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1762 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1763 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1764 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1765
1766 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1767 {
1768         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1769         if (r_hlsl_permutation != perm)
1770         {
1771                 r_hlsl_permutation = perm;
1772                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1773                 {
1774                         if (!r_hlsl_permutation->compiled)
1775                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1776                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1777                         {
1778                                 // remove features until we find a valid permutation
1779                                 int i;
1780                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1781                                 {
1782                                         // reduce i more quickly whenever it would not remove any bits
1783                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1784                                         if (!(permutation & j))
1785                                                 continue;
1786                                         permutation -= j;
1787                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1788                                         if (!r_hlsl_permutation->compiled)
1789                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1790                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1791                                                 break;
1792                                 }
1793                                 if (i >= SHADERPERMUTATION_COUNT)
1794                                 {
1795                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1796                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1797                                         return; // no bit left to clear, entire mode is broken
1798                                 }
1799                         }
1800                 }
1801                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1802                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1803         }
1804         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1805         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1806         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1807 }
1808 #endif
1809
1810 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1811 {
1812         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1813         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1814         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1815         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1816 }
1817
1818 void R_GLSL_Restart_f(void)
1819 {
1820         unsigned int i, limit;
1821         if (glslshaderstring)
1822                 Mem_Free(glslshaderstring);
1823         glslshaderstring = NULL;
1824         if (hlslshaderstring)
1825                 Mem_Free(hlslshaderstring);
1826         hlslshaderstring = NULL;
1827         switch(vid.renderpath)
1828         {
1829         case RENDERPATH_D3D9:
1830 #ifdef SUPPORTD3D
1831                 {
1832                         r_hlsl_permutation_t *p;
1833                         r_hlsl_permutation = NULL;
1834                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1835                         for (i = 0;i < limit;i++)
1836                         {
1837                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1838                                 {
1839                                         if (p->vertexshader)
1840                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1841                                         if (p->pixelshader)
1842                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1843                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1844                                 }
1845                         }
1846                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1847                 }
1848 #endif
1849                 break;
1850         case RENDERPATH_D3D10:
1851                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1852                 break;
1853         case RENDERPATH_D3D11:
1854                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1855                 break;
1856         case RENDERPATH_GL20:
1857         case RENDERPATH_GLES2:
1858                 {
1859                         r_glsl_permutation_t *p;
1860                         r_glsl_permutation = NULL;
1861                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1862                         for (i = 0;i < limit;i++)
1863                         {
1864                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1865                                 {
1866                                         GL_Backend_FreeProgram(p->program);
1867                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1868                                 }
1869                         }
1870                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1871                 }
1872                 break;
1873         case RENDERPATH_GL11:
1874         case RENDERPATH_GL13:
1875         case RENDERPATH_GLES1:
1876                 break;
1877         case RENDERPATH_SOFT:
1878                 break;
1879         }
1880 }
1881
1882 static void R_GLSL_DumpShader_f(void)
1883 {
1884         int i, language, mode, dupe;
1885         char *text;
1886         shadermodeinfo_t *modeinfo;
1887         qfile_t *file;
1888
1889         for (language = 0;language < 2;language++)
1890         {
1891                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1892                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1893                 {
1894                         // don't dump the same file multiple times (most or all shaders come from the same file)
1895                         for (dupe = mode - 1;dupe >= 0;dupe--)
1896                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1897                                         break;
1898                         if (dupe >= 0)
1899                                 continue;
1900                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1901                         if (!text)
1902                                 continue;
1903                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1904                         if (file)
1905                         {
1906                                 FS_Print(file, "/* The engine may define the following macros:\n");
1907                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1908                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1909                                         FS_Print(file, modeinfo[i].pretext);
1910                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1911                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1912                                 FS_Print(file, "*/\n");
1913                                 FS_Print(file, text);
1914                                 FS_Close(file);
1915                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1916                         }
1917                         else
1918                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1919                         Mem_Free(text);
1920                 }
1921         }
1922 }
1923
1924 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1925 {
1926         unsigned int permutation = 0;
1927         if (r_trippy.integer && !notrippy)
1928                 permutation |= SHADERPERMUTATION_TRIPPY;
1929         permutation |= SHADERPERMUTATION_VIEWTINT;
1930         if (first)
1931                 permutation |= SHADERPERMUTATION_DIFFUSE;
1932         if (second)
1933                 permutation |= SHADERPERMUTATION_SPECULAR;
1934         if (texturemode == GL_MODULATE)
1935                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1936         else if (texturemode == GL_ADD)
1937                 permutation |= SHADERPERMUTATION_GLOW;
1938         else if (texturemode == GL_DECAL)
1939                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1940         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1941                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1942         if (suppresstexalpha)
1943                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1944         if (!second)
1945                 texturemode = GL_MODULATE;
1946         if (vid.allowalphatocoverage)
1947                 GL_AlphaToCoverage(false);
1948         switch (vid.renderpath)
1949         {
1950         case RENDERPATH_D3D9:
1951 #ifdef SUPPORTD3D
1952                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1953                 R_Mesh_TexBind(GL20TU_FIRST , first );
1954                 R_Mesh_TexBind(GL20TU_SECOND, second);
1955                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1956                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1957 #endif
1958                 break;
1959         case RENDERPATH_D3D10:
1960                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961                 break;
1962         case RENDERPATH_D3D11:
1963                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1964                 break;
1965         case RENDERPATH_GL20:
1966         case RENDERPATH_GLES2:
1967                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1968                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1969                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1970                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1971                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1972                 break;
1973         case RENDERPATH_GL13:
1974         case RENDERPATH_GLES1:
1975                 R_Mesh_TexBind(0, first );
1976                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1977                 R_Mesh_TexBind(1, second);
1978                 if (second)
1979                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1980                 break;
1981         case RENDERPATH_GL11:
1982                 R_Mesh_TexBind(0, first );
1983                 break;
1984         case RENDERPATH_SOFT:
1985                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1986                 R_Mesh_TexBind(GL20TU_FIRST , first );
1987                 R_Mesh_TexBind(GL20TU_SECOND, second);
1988                 break;
1989         }
1990 }
1991
1992 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1993 {
1994         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1995 }
1996
1997 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
1998 {
1999         unsigned int permutation = 0;
2000         if (r_trippy.integer && !notrippy)
2001                 permutation |= SHADERPERMUTATION_TRIPPY;
2002         if (depthrgb)
2003                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2004         if (skeletal)
2005                 permutation |= SHADERPERMUTATION_SKELETAL;
2006
2007         if (vid.allowalphatocoverage)
2008                 GL_AlphaToCoverage(false);
2009         switch (vid.renderpath)
2010         {
2011         case RENDERPATH_D3D9:
2012 #ifdef SUPPORTD3D
2013                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2014 #endif
2015                 break;
2016         case RENDERPATH_D3D10:
2017                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2018                 break;
2019         case RENDERPATH_D3D11:
2020                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2021                 break;
2022         case RENDERPATH_GL20:
2023         case RENDERPATH_GLES2:
2024                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2025                 break;
2026         case RENDERPATH_GL13:
2027         case RENDERPATH_GLES1:
2028                 R_Mesh_TexBind(0, 0);
2029                 R_Mesh_TexBind(1, 0);
2030                 break;
2031         case RENDERPATH_GL11:
2032                 R_Mesh_TexBind(0, 0);
2033                 break;
2034         case RENDERPATH_SOFT:
2035                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2036                 break;
2037         }
2038 }
2039
2040 extern qboolean r_shadow_usingdeferredprepass;
2041 extern rtexture_t *r_shadow_attenuationgradienttexture;
2042 extern rtexture_t *r_shadow_attenuation2dtexture;
2043 extern rtexture_t *r_shadow_attenuation3dtexture;
2044 extern qboolean r_shadow_usingshadowmap2d;
2045 extern qboolean r_shadow_usingshadowmaportho;
2046 extern float r_shadow_shadowmap_texturescale[2];
2047 extern float r_shadow_shadowmap_parameters[4];
2048 extern qboolean r_shadow_shadowmapvsdct;
2049 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2050 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2051 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2052 extern matrix4x4_t r_shadow_shadowmapmatrix;
2053 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2054 extern int r_shadow_prepass_width;
2055 extern int r_shadow_prepass_height;
2056 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2057 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2058 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2059 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2060
2061 #define BLENDFUNC_ALLOWS_COLORMOD      1
2062 #define BLENDFUNC_ALLOWS_FOG           2
2063 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2064 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2065 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2066 static int R_BlendFuncFlags(int src, int dst)
2067 {
2068         int r = 0;
2069
2070         // a blendfunc allows colormod if:
2071         // a) it can never keep the destination pixel invariant, or
2072         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2073         // this is to prevent unintended side effects from colormod
2074
2075         // a blendfunc allows fog if:
2076         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2077         // this is to prevent unintended side effects from fog
2078
2079         // these checks are the output of fogeval.pl
2080
2081         r |= BLENDFUNC_ALLOWS_COLORMOD;
2082         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2083         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2084         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2085         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2086         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2087         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2088         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2089         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2090         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2091         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2092         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2093         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2094         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2095         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2096         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2100         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2101         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2102         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2103
2104         return r;
2105 }
2106
2107 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2108 {
2109         // select a permutation of the lighting shader appropriate to this
2110         // combination of texture, entity, light source, and fogging, only use the
2111         // minimum features necessary to avoid wasting rendering time in the
2112         // fragment shader on features that are not being used
2113         unsigned int permutation = 0;
2114         unsigned int mode = 0;
2115         int blendfuncflags;
2116         static float dummy_colormod[3] = {1, 1, 1};
2117         float *colormod = rsurface.colormod;
2118         float m16f[16];
2119         matrix4x4_t tempmatrix;
2120         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2121         if (r_trippy.integer && !notrippy)
2122                 permutation |= SHADERPERMUTATION_TRIPPY;
2123         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2124                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2125         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2126                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2127         if (rsurfacepass == RSURFPASS_BACKGROUND)
2128         {
2129                 // distorted background
2130                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2131                 {
2132                         mode = SHADERMODE_WATER;
2133                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2134                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2135                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2136                         {
2137                                 // this is the right thing to do for wateralpha
2138                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2139                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2140                         }
2141                         else
2142                         {
2143                                 // this is the right thing to do for entity alpha
2144                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2145                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146                         }
2147                 }
2148                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2149                 {
2150                         mode = SHADERMODE_REFRACTION;
2151                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2152                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2153                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2154                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2155                 }
2156                 else
2157                 {
2158                         mode = SHADERMODE_GENERIC;
2159                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2160                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2161                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2162                 }
2163                 if (vid.allowalphatocoverage)
2164                         GL_AlphaToCoverage(false);
2165         }
2166         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2167         {
2168                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2169                 {
2170                         switch(rsurface.texture->offsetmapping)
2171                         {
2172                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2173                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2174                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2175                         case OFFSETMAPPING_OFF: break;
2176                         }
2177                 }
2178                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2179                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2180                 // normalmap (deferred prepass), may use alpha test on diffuse
2181                 mode = SHADERMODE_DEFERREDGEOMETRY;
2182                 GL_BlendFunc(GL_ONE, GL_ZERO);
2183                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2184                 if (vid.allowalphatocoverage)
2185                         GL_AlphaToCoverage(false);
2186         }
2187         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2188         {
2189                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2190                 {
2191                         switch(rsurface.texture->offsetmapping)
2192                         {
2193                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2194                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2195                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2196                         case OFFSETMAPPING_OFF: break;
2197                         }
2198                 }
2199                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2200                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2201                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2202                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2203                 // light source
2204                 mode = SHADERMODE_LIGHTSOURCE;
2205                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2206                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2207                 if (diffusescale > 0)
2208                         permutation |= SHADERPERMUTATION_DIFFUSE;
2209                 if (specularscale > 0)
2210                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2211                 if (r_refdef.fogenabled)
2212                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2213                 if (rsurface.texture->colormapping)
2214                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2215                 if (r_shadow_usingshadowmap2d)
2216                 {
2217                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2218                         if(r_shadow_shadowmapvsdct)
2219                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2220
2221                         if (r_shadow_shadowmap2ddepthbuffer)
2222                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2223                 }
2224                 if (rsurface.texture->reflectmasktexture)
2225                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2226                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2227                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2228                 if (vid.allowalphatocoverage)
2229                         GL_AlphaToCoverage(false);
2230         }
2231         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2232         {
2233                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2234                 {
2235                         switch(rsurface.texture->offsetmapping)
2236                         {
2237                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2238                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2239                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2240                         case OFFSETMAPPING_OFF: break;
2241                         }
2242                 }
2243                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2244                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2245                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2246                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2247                 // unshaded geometry (fullbright or ambient model lighting)
2248                 mode = SHADERMODE_FLATCOLOR;
2249                 ambientscale = diffusescale = specularscale = 0;
2250                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2251                         permutation |= SHADERPERMUTATION_GLOW;
2252                 if (r_refdef.fogenabled)
2253                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2254                 if (rsurface.texture->colormapping)
2255                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2256                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2257                 {
2258                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2259                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2260
2261                         if (r_shadow_shadowmap2ddepthbuffer)
2262                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2263                 }
2264                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2265                         permutation |= SHADERPERMUTATION_REFLECTION;
2266                 if (rsurface.texture->reflectmasktexture)
2267                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2268                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2269                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2270                 // when using alphatocoverage, we don't need alphakill
2271                 if (vid.allowalphatocoverage)
2272                 {
2273                         if (r_transparent_alphatocoverage.integer)
2274                         {
2275                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2276                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2277                         }
2278                         else
2279                                 GL_AlphaToCoverage(false);
2280                 }
2281         }
2282         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2283         {
2284                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2285                 {
2286                         switch(rsurface.texture->offsetmapping)
2287                         {
2288                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2289                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2290                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2291                         case OFFSETMAPPING_OFF: break;
2292                         }
2293                 }
2294                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2295                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2296                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2297                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2298                 // directional model lighting
2299                 mode = SHADERMODE_LIGHTDIRECTION;
2300                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2301                         permutation |= SHADERPERMUTATION_GLOW;
2302                 permutation |= SHADERPERMUTATION_DIFFUSE;
2303                 if (specularscale > 0)
2304                         permutation |= SHADERPERMUTATION_SPECULAR;
2305                 if (r_refdef.fogenabled)
2306                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2307                 if (rsurface.texture->colormapping)
2308                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2309                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2310                 {
2311                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2312                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2313
2314                         if (r_shadow_shadowmap2ddepthbuffer)
2315                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2316                 }
2317                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2318                         permutation |= SHADERPERMUTATION_REFLECTION;
2319                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2320                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2321                 if (rsurface.texture->reflectmasktexture)
2322                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2323                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2324                 {
2325                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2326                         if (r_shadow_bouncegriddirectional)
2327                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2328                 }
2329                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2330                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2331                 // when using alphatocoverage, we don't need alphakill
2332                 if (vid.allowalphatocoverage)
2333                 {
2334                         if (r_transparent_alphatocoverage.integer)
2335                         {
2336                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2337                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2338                         }
2339                         else
2340                                 GL_AlphaToCoverage(false);
2341                 }
2342         }
2343         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2344         {
2345                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2346                 {
2347                         switch(rsurface.texture->offsetmapping)
2348                         {
2349                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2350                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2351                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2352                         case OFFSETMAPPING_OFF: break;
2353                         }
2354                 }
2355                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2356                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2357                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2358                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2359                 // ambient model lighting
2360                 mode = SHADERMODE_LIGHTDIRECTION;
2361                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2362                         permutation |= SHADERPERMUTATION_GLOW;
2363                 if (r_refdef.fogenabled)
2364                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2365                 if (rsurface.texture->colormapping)
2366                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2367                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2368                 {
2369                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2370                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2371
2372                         if (r_shadow_shadowmap2ddepthbuffer)
2373                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2374                 }
2375                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376                         permutation |= SHADERPERMUTATION_REFLECTION;
2377                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2378                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2379                 if (rsurface.texture->reflectmasktexture)
2380                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2381                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2382                 {
2383                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2384                         if (r_shadow_bouncegriddirectional)
2385                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2386                 }
2387                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2388                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2389                 // when using alphatocoverage, we don't need alphakill
2390                 if (vid.allowalphatocoverage)
2391                 {
2392                         if (r_transparent_alphatocoverage.integer)
2393                         {
2394                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2395                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2396                         }
2397                         else
2398                                 GL_AlphaToCoverage(false);
2399                 }
2400         }
2401         else
2402         {
2403                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2404                 {
2405                         switch(rsurface.texture->offsetmapping)
2406                         {
2407                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2408                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2409                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2410                         case OFFSETMAPPING_OFF: break;
2411                         }
2412                 }
2413                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2414                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2415                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2416                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2417                 // lightmapped wall
2418                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2419                         permutation |= SHADERPERMUTATION_GLOW;
2420                 if (r_refdef.fogenabled)
2421                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2422                 if (rsurface.texture->colormapping)
2423                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2424                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2425                 {
2426                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2427                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2428
2429                         if (r_shadow_shadowmap2ddepthbuffer)
2430                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2431                 }
2432                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2433                         permutation |= SHADERPERMUTATION_REFLECTION;
2434                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2435                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2436                 if (rsurface.texture->reflectmasktexture)
2437                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2438                 if (FAKELIGHT_ENABLED)
2439                 {
2440                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2441                         mode = SHADERMODE_FAKELIGHT;
2442                         permutation |= SHADERPERMUTATION_DIFFUSE;
2443                         if (specularscale > 0)
2444                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2445                 }
2446                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2447                 {
2448                         // deluxemapping (light direction texture)
2449                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2450                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2451                         else
2452                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2453                         permutation |= SHADERPERMUTATION_DIFFUSE;
2454                         if (specularscale > 0)
2455                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2456                 }
2457                 else if (r_glsl_deluxemapping.integer >= 2)
2458                 {
2459                         // fake deluxemapping (uniform light direction in tangentspace)
2460                         if (rsurface.uselightmaptexture)
2461                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2462                         else
2463                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2464                         permutation |= SHADERPERMUTATION_DIFFUSE;
2465                         if (specularscale > 0)
2466                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2467                 }
2468                 else if (rsurface.uselightmaptexture)
2469                 {
2470                         // ordinary lightmapping (q1bsp, q3bsp)
2471                         mode = SHADERMODE_LIGHTMAP;
2472                 }
2473                 else
2474                 {
2475                         // ordinary vertex coloring (q3bsp)
2476                         mode = SHADERMODE_VERTEXCOLOR;
2477                 }
2478                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2479                 {
2480                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2481                         if (r_shadow_bouncegriddirectional)
2482                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2483                 }
2484                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2485                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2486                 // when using alphatocoverage, we don't need alphakill
2487                 if (vid.allowalphatocoverage)
2488                 {
2489                         if (r_transparent_alphatocoverage.integer)
2490                         {
2491                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2492                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2493                         }
2494                         else
2495                                 GL_AlphaToCoverage(false);
2496                 }
2497         }
2498         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2499                 colormod = dummy_colormod;
2500         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2501                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2502         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2503                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2504         switch(vid.renderpath)
2505         {
2506         case RENDERPATH_D3D9:
2507 #ifdef SUPPORTD3D
2508                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2509                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2510                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2511                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2512                 if (mode == SHADERMODE_LIGHTSOURCE)
2513                 {
2514                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2515                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2516                 }
2517                 else
2518                 {
2519                         if (mode == SHADERMODE_LIGHTDIRECTION)
2520                         {
2521                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2522                         }
2523                 }
2524                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2525                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2526                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2527                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2528                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2529
2530                 if (mode == SHADERMODE_LIGHTSOURCE)
2531                 {
2532                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2533                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2534                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2536                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2537
2538                         // additive passes are only darkened by fog, not tinted
2539                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2540                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2541                 }
2542                 else
2543                 {
2544                         if (mode == SHADERMODE_FLATCOLOR)
2545                         {
2546                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2547                         }
2548                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2549                         {
2550                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2551                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2553                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2556                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2557                         }
2558                         else
2559                         {
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2565                         }
2566                         // additive passes are only darkened by fog, not tinted
2567                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2569                         else
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2571                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2572                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2573                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2574                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2575                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2576                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2577                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2578                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2579                         if (mode == SHADERMODE_WATER)
2580                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2581                 }
2582                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2583                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2584                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2585                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2586                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2587                 if (rsurface.texture->pantstexture)
2588                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2589                 else
2590                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2591                 if (rsurface.texture->shirttexture)
2592                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2593                 else
2594                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2595                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2596                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2597                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2598                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2599                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2600                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2601                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2602                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2603                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2604                         );
2605                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2606                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2607                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2608                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2609
2610                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2611                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2612                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2613                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2614                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2615                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2616                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2617                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2618                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2619                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2620                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2621                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2622                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2623                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2624                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2625                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2626                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2627                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2628                 {
2629                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2630                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2631                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2632                 }
2633                 else
2634                 {
2635                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2636                 }
2637 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2638                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2639                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2640                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2641                 {
2642                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2643                         if (rsurface.rtlight)
2644                         {
2645                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2646                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2647                         }
2648                 }
2649 #endif
2650                 break;
2651         case RENDERPATH_D3D10:
2652                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2653                 break;
2654         case RENDERPATH_D3D11:
2655                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2656                 break;
2657         case RENDERPATH_GL20:
2658         case RENDERPATH_GLES2:
2659                 if (!vid.useinterleavedarrays)
2660                 {
2661                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2662                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2663                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2664                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2665                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2666                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2667                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2668                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2669                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2670                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2671                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2672                 }
2673                 else
2674                 {
2675                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2676                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2677                 }
2678                 // this has to be after RSurf_PrepareVerticesForBatch
2679                 if (rsurface.batchskeletaltransform3x4)
2680                         permutation |= SHADERPERMUTATION_SKELETAL;
2681                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2682                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2683                 if (mode == SHADERMODE_LIGHTSOURCE)
2684                 {
2685                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2686                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2687                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2688                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2689                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2690                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2691         
2692                         // additive passes are only darkened by fog, not tinted
2693                         if (r_glsl_permutation->loc_FogColor >= 0)
2694                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2695                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2696                 }
2697                 else
2698                 {
2699                         if (mode == SHADERMODE_FLATCOLOR)
2700                         {
2701                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2702                         }
2703                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2704                         {
2705                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2706                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2707                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2708                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2709                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2710                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2711                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2712                         }
2713                         else
2714                         {
2715                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2716                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2717                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2718                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2719                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2720                         }
2721                         // additive passes are only darkened by fog, not tinted
2722                         if (r_glsl_permutation->loc_FogColor >= 0)
2723                         {
2724                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2725                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2726                                 else
2727                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2728                         }
2729                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2730                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2731                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2732                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2733                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2734                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2735                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2736                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2737                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2738                 }
2739                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2740                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2741                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2742                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2743                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2744
2745                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2746                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2747                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2748                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2749                 {
2750                         if (rsurface.texture->pantstexture)
2751                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2752                         else
2753                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2754                 }
2755                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2756                 {
2757                         if (rsurface.texture->shirttexture)
2758                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2759                         else
2760                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2761                 }
2762                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2763                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2764                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2765                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2766                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2767                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2768                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2769                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2770                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2771                         );
2772                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2773                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2774                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2775                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2776                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2777                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2778
2779                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2780                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2781                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2782                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2783                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2784                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2785                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2786                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2787                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2788                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2789                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2790                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2791                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2792                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2793                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2794                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2795                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2796                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2797                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2798                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2799                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2800                 {
2801                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2802                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2803                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2804                 }
2805                 else
2806                 {
2807                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2808                 }
2809                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2810                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2811                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2812                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2813                 {
2814                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2815                         if (rsurface.rtlight)
2816                         {
2817                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2818                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2819                         }
2820                 }
2821                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2822                 if (r_glsl_permutation->loc_Skeletal_Transform12 >= 0 && rsurface.batchskeletalnumtransforms > 0)
2823                         qglUniform4fv(r_glsl_permutation->loc_Skeletal_Transform12, rsurface.batchskeletalnumtransforms*3, rsurface.batchskeletaltransform3x4);
2824                 CHECKGLERROR
2825                 break;
2826         case RENDERPATH_GL11:
2827         case RENDERPATH_GL13:
2828         case RENDERPATH_GLES1:
2829                 break;
2830         case RENDERPATH_SOFT:
2831                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2832                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2833                 R_SetupShader_SetPermutationSoft(mode, permutation);
2834                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2835                 if (mode == SHADERMODE_LIGHTSOURCE)
2836                 {
2837                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2838                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2839                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2840                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2841                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2842                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2843         
2844                         // additive passes are only darkened by fog, not tinted
2845                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2846                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2847                 }
2848                 else
2849                 {
2850                         if (mode == SHADERMODE_FLATCOLOR)
2851                         {
2852                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2853                         }
2854                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2855                         {
2856                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2857                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2858                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2859                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2860                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2861                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2862                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2863                         }
2864                         else
2865                         {
2866                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2867                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2868                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2871                         }
2872                         // additive passes are only darkened by fog, not tinted
2873                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2875                         else
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2877                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2878                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2879                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2880                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2881                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2882                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2883                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2884                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2885                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2886                 }
2887                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2888                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2889                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2890                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2891                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2892
2893                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2894                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2895                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2896                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2897                 {
2898                         if (rsurface.texture->pantstexture)
2899                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2900                         else
2901                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2902                 }
2903                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2904                 {
2905                         if (rsurface.texture->shirttexture)
2906                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2907                         else
2908                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2909                 }
2910                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2911                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2912                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2913                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2914                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2915                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2916                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2917                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2918                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2919                         );
2920                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2921                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2922                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2923                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2924
2925                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2926                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2927                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2928                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2929                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2930                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2931                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2932                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2933                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2934                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2935                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2936                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2937                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2938                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2939                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2940                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2941                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2942                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2943                 {
2944                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2945                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2946                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2947                 }
2948                 else
2949                 {
2950                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2951                 }
2952 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2953                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2954                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2955                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2956                 {
2957                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2958                         if (rsurface.rtlight)
2959                         {
2960                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2961                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2962                         }
2963                 }
2964                 break;
2965         }
2966 }
2967
2968 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2969 {
2970         // select a permutation of the lighting shader appropriate to this
2971         // combination of texture, entity, light source, and fogging, only use the
2972         // minimum features necessary to avoid wasting rendering time in the
2973         // fragment shader on features that are not being used
2974         unsigned int permutation = 0;
2975         unsigned int mode = 0;
2976         const float *lightcolorbase = rtlight->currentcolor;
2977         float ambientscale = rtlight->ambientscale;
2978         float diffusescale = rtlight->diffusescale;
2979         float specularscale = rtlight->specularscale;
2980         // this is the location of the light in view space
2981         vec3_t viewlightorigin;
2982         // this transforms from view space (camera) to light space (cubemap)
2983         matrix4x4_t viewtolight;
2984         matrix4x4_t lighttoview;
2985         float viewtolight16f[16];
2986         // light source
2987         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2988         if (rtlight->currentcubemap != r_texture_whitecube)
2989                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2990         if (diffusescale > 0)
2991                 permutation |= SHADERPERMUTATION_DIFFUSE;
2992         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2993                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2994         if (r_shadow_usingshadowmap2d)
2995         {
2996                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2997                 if (r_shadow_shadowmapvsdct)
2998                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2999
3000                 if (r_shadow_shadowmap2ddepthbuffer)
3001                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3002         }
3003         if (vid.allowalphatocoverage)
3004                 GL_AlphaToCoverage(false);
3005         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3006         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3007         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3008         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3009         switch(vid.renderpath)
3010         {
3011         case RENDERPATH_D3D9:
3012 #ifdef SUPPORTD3D
3013                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3014                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3015                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3016                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3017                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3018                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3019                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3020                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3021                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3022                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3023                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3024
3025                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3026                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3027                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3028                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3029                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3030 #endif
3031                 break;
3032         case RENDERPATH_D3D10:
3033                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3034                 break;
3035         case RENDERPATH_D3D11:
3036                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3037                 break;
3038         case RENDERPATH_GL20:
3039         case RENDERPATH_GLES2:
3040                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3041                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3042                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3043                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3044                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3045                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3046                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3047                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3048                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3049                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3050                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3051
3052                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3053                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3054                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3055                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3056                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3057                 break;
3058         case RENDERPATH_GL11:
3059         case RENDERPATH_GL13:
3060         case RENDERPATH_GLES1:
3061                 break;
3062         case RENDERPATH_SOFT:
3063                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3064                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3065                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3066                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3067                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3068                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3069                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3070                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3071                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3072                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3073                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3074
3075                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3076                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3077                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3078                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3079                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3080                 break;
3081         }
3082 }
3083
3084 #define SKINFRAME_HASH 1024
3085
3086 typedef struct
3087 {
3088         int loadsequence; // incremented each level change
3089         memexpandablearray_t array;
3090         skinframe_t *hash[SKINFRAME_HASH];
3091 }
3092 r_skinframe_t;
3093 r_skinframe_t r_skinframe;
3094
3095 void R_SkinFrame_PrepareForPurge(void)
3096 {
3097         r_skinframe.loadsequence++;
3098         // wrap it without hitting zero
3099         if (r_skinframe.loadsequence >= 200)
3100                 r_skinframe.loadsequence = 1;
3101 }
3102
3103 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3104 {
3105         if (!skinframe)
3106                 return;
3107         // mark the skinframe as used for the purging code
3108         skinframe->loadsequence = r_skinframe.loadsequence;
3109 }
3110
3111 void R_SkinFrame_Purge(void)
3112 {
3113         int i;
3114         skinframe_t *s;
3115         for (i = 0;i < SKINFRAME_HASH;i++)
3116         {
3117                 for (s = r_skinframe.hash[i];s;s = s->next)
3118                 {
3119                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3120                         {
3121                                 if (s->merged == s->base)
3122                                         s->merged = NULL;
3123                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3124                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3125                                 R_PurgeTexture(s->merged);s->merged = NULL;
3126                                 R_PurgeTexture(s->base  );s->base   = NULL;
3127                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3128                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3129                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3130                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3131                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3132                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3133                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3134                                 s->loadsequence = 0;
3135                         }
3136                 }
3137         }
3138 }
3139
3140 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3141         skinframe_t *item;
3142         char basename[MAX_QPATH];
3143
3144         Image_StripImageExtension(name, basename, sizeof(basename));
3145
3146         if( last == NULL ) {
3147                 int hashindex;
3148                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3149                 item = r_skinframe.hash[hashindex];
3150         } else {
3151                 item = last->next;
3152         }
3153
3154         // linearly search through the hash bucket
3155         for( ; item ; item = item->next ) {
3156                 if( !strcmp( item->basename, basename ) ) {
3157                         return item;
3158                 }
3159         }
3160         return NULL;
3161 }
3162
3163 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3164 {
3165         skinframe_t *item;
3166         int hashindex;
3167         char basename[MAX_QPATH];
3168
3169         Image_StripImageExtension(name, basename, sizeof(basename));
3170
3171         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3172         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3173                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3174                         break;
3175
3176         if (!item) {
3177                 rtexture_t *dyntexture;
3178                 // check whether its a dynamic texture
3179                 dyntexture = CL_GetDynTexture( basename );
3180                 if (!add && !dyntexture)
3181                         return NULL;
3182                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3183                 memset(item, 0, sizeof(*item));
3184                 strlcpy(item->basename, basename, sizeof(item->basename));
3185                 item->base = dyntexture; // either NULL or dyntexture handle
3186                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3187                 item->comparewidth = comparewidth;
3188                 item->compareheight = compareheight;
3189                 item->comparecrc = comparecrc;
3190                 item->next = r_skinframe.hash[hashindex];
3191                 r_skinframe.hash[hashindex] = item;
3192         }
3193         else if (textureflags & TEXF_FORCE_RELOAD)
3194         {
3195                 rtexture_t *dyntexture;
3196                 // check whether its a dynamic texture
3197                 dyntexture = CL_GetDynTexture( basename );
3198                 if (!add && !dyntexture)
3199                         return NULL;
3200                 if (item->merged == item->base)
3201                         item->merged = NULL;
3202                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3203                 R_PurgeTexture(item->stain );item->stain  = NULL;
3204                 R_PurgeTexture(item->merged);item->merged = NULL;
3205                 R_PurgeTexture(item->base  );item->base   = NULL;
3206                 R_PurgeTexture(item->pants );item->pants  = NULL;
3207                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3208                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3209                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3210                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3211                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3212         R_PurgeTexture(item->reflect);item->reflect = NULL;
3213                 item->loadsequence = 0;
3214         }
3215         else if( item->base == NULL )
3216         {
3217                 rtexture_t *dyntexture;
3218                 // check whether its a dynamic texture
3219                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3220                 dyntexture = CL_GetDynTexture( basename );
3221                 item->base = dyntexture; // either NULL or dyntexture handle
3222         }
3223
3224         R_SkinFrame_MarkUsed(item);
3225         return item;
3226 }
3227
3228 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3229         { \
3230                 unsigned long long avgcolor[5], wsum; \
3231                 int pix, comp, w; \
3232                 avgcolor[0] = 0; \
3233                 avgcolor[1] = 0; \
3234                 avgcolor[2] = 0; \
3235                 avgcolor[3] = 0; \
3236                 avgcolor[4] = 0; \
3237                 wsum = 0; \
3238                 for(pix = 0; pix < cnt; ++pix) \
3239                 { \
3240                         w = 0; \
3241                         for(comp = 0; comp < 3; ++comp) \
3242                                 w += getpixel; \
3243                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3244                         { \
3245                                 ++wsum; \
3246                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3247                                 w = getpixel; \
3248                                 for(comp = 0; comp < 3; ++comp) \
3249                                         avgcolor[comp] += getpixel * w; \
3250                                 avgcolor[3] += w; \
3251                         } \
3252                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3253                         avgcolor[4] += getpixel; \
3254                 } \
3255                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3256                         avgcolor[3] = 1; \
3257                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3258                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3259                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3260                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3261         }
3262
3263 extern cvar_t gl_picmip;
3264 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3265 {
3266         int j;
3267         unsigned char *pixels;
3268         unsigned char *bumppixels;
3269         unsigned char *basepixels = NULL;
3270         int basepixels_width = 0;
3271         int basepixels_height = 0;
3272         skinframe_t *skinframe;
3273         rtexture_t *ddsbase = NULL;
3274         qboolean ddshasalpha = false;
3275         float ddsavgcolor[4];
3276         char basename[MAX_QPATH];
3277         int miplevel = R_PicmipForFlags(textureflags);
3278         int savemiplevel = miplevel;
3279         int mymiplevel;
3280         char vabuf[1024];
3281
3282         if (cls.state == ca_dedicated)
3283                 return NULL;
3284
3285         // return an existing skinframe if already loaded
3286         // if loading of the first image fails, don't make a new skinframe as it
3287         // would cause all future lookups of this to be missing
3288         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3289         if (skinframe && skinframe->base)
3290                 return skinframe;
3291
3292         Image_StripImageExtension(name, basename, sizeof(basename));
3293
3294         // check for DDS texture file first
3295         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3296         {
3297                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3298                 if (basepixels == NULL)
3299                         return NULL;
3300         }
3301
3302         // FIXME handle miplevel
3303
3304         if (developer_loading.integer)
3305                 Con_Printf("loading skin \"%s\"\n", name);
3306
3307         // we've got some pixels to store, so really allocate this new texture now
3308         if (!skinframe)
3309                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3310         textureflags &= ~TEXF_FORCE_RELOAD;
3311         skinframe->stain = NULL;
3312         skinframe->merged = NULL;
3313         skinframe->base = NULL;
3314         skinframe->pants = NULL;
3315         skinframe->shirt = NULL;
3316         skinframe->nmap = NULL;
3317         skinframe->gloss = NULL;
3318         skinframe->glow = NULL;
3319         skinframe->fog = NULL;
3320         skinframe->reflect = NULL;
3321         skinframe->hasalpha = false;
3322
3323         if (ddsbase)
3324         {
3325                 skinframe->base = ddsbase;
3326                 skinframe->hasalpha = ddshasalpha;
3327                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3328                 if (r_loadfog && skinframe->hasalpha)
3329                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3330                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3331         }
3332         else
3333         {
3334                 basepixels_width = image_width;
3335                 basepixels_height = image_height;
3336                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3337                 if (textureflags & TEXF_ALPHA)
3338                 {
3339                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3340                         {
3341                                 if (basepixels[j] < 255)
3342                                 {
3343                                         skinframe->hasalpha = true;
3344                                         break;
3345                                 }
3346                         }
3347                         if (r_loadfog && skinframe->hasalpha)
3348                         {
3349                                 // has transparent pixels
3350                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3351                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3352                                 {
3353                                         pixels[j+0] = 255;
3354                                         pixels[j+1] = 255;
3355                                         pixels[j+2] = 255;
3356                                         pixels[j+3] = basepixels[j+3];
3357                                 }
3358                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3359                                 Mem_Free(pixels);
3360                         }
3361                 }
3362                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3363 #ifndef USE_GLES2
3364                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3365                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3366                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3367                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3368                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3369 #endif
3370         }
3371
3372         if (r_loaddds)
3373         {
3374                 mymiplevel = savemiplevel;
3375                 if (r_loadnormalmap)
3376                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
3377                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3378                 if (r_loadgloss)
3379                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3380                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3381                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3382                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3383         }
3384
3385         // _norm is the name used by tenebrae and has been adopted as standard
3386         if (r_loadnormalmap && skinframe->nmap == NULL)
3387         {
3388                 mymiplevel = savemiplevel;
3389                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3390                 {
3391                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3392                         Mem_Free(pixels);
3393                         pixels = NULL;
3394                 }
3395                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3396                 {
3397                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3398                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3399                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3400                         Mem_Free(pixels);
3401                         Mem_Free(bumppixels);
3402                 }
3403                 else if (r_shadow_bumpscale_basetexture.value > 0)
3404                 {
3405                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3406                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3407                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3408                         Mem_Free(pixels);
3409                 }
3410 #ifndef USE_GLES2
3411                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3412                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3413 #endif
3414         }
3415
3416         // _luma is supported only for tenebrae compatibility
3417         // _glow is the preferred name
3418         mymiplevel = savemiplevel;
3419         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3420         {
3421                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3422 #ifndef USE_GLES2
3423                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3424                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3425 #endif
3426                 Mem_Free(pixels);pixels = NULL;
3427         }
3428
3429         mymiplevel = savemiplevel;
3430         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3431         {
3432                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3433 #ifndef USE_GLES2
3434                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3435                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3436 #endif
3437                 Mem_Free(pixels);
3438                 pixels = NULL;
3439         }
3440
3441         mymiplevel = savemiplevel;
3442         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3443         {
3444                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3445 #ifndef USE_GLES2
3446                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3447                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3448 #endif
3449                 Mem_Free(pixels);
3450                 pixels = NULL;
3451         }
3452
3453         mymiplevel = savemiplevel;
3454         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3455         {
3456                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3457 #ifndef USE_GLES2
3458                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3459                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3460 #endif
3461                 Mem_Free(pixels);
3462                 pixels = NULL;
3463         }
3464
3465         mymiplevel = savemiplevel;
3466         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3467         {
3468                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3469 #ifndef USE_GLES2
3470                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3471                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3472 #endif
3473                 Mem_Free(pixels);
3474                 pixels = NULL;
3475         }
3476
3477         if (basepixels)
3478                 Mem_Free(basepixels);
3479
3480         return skinframe;
3481 }
3482
3483 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3484 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3485 {
3486         int i;
3487         unsigned char *temp1, *temp2;
3488         skinframe_t *skinframe;
3489         char vabuf[1024];
3490
3491         if (cls.state == ca_dedicated)
3492                 return NULL;
3493
3494         // if already loaded just return it, otherwise make a new skinframe
3495         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3496         if (skinframe->base)
3497                 return skinframe;
3498         textureflags &= ~TEXF_FORCE_RELOAD;
3499
3500         skinframe->stain = NULL;
3501         skinframe->merged = NULL;
3502         skinframe->base = NULL;
3503         skinframe->pants = NULL;
3504         skinframe->shirt = NULL;
3505         skinframe->nmap = NULL;
3506         skinframe->gloss = NULL;
3507         skinframe->glow = NULL;
3508         skinframe->fog = NULL;
3509         skinframe->reflect = NULL;
3510         skinframe->hasalpha = false;
3511
3512         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3513         if (!skindata)
3514                 return NULL;
3515
3516         if (developer_loading.integer)
3517                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3518
3519         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3520         {
3521                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3522                 temp2 = temp1 + width * height * 4;
3523                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3524                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3525                 Mem_Free(temp1);
3526         }
3527         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3528         if (textureflags & TEXF_ALPHA)
3529         {
3530                 for (i = 3;i < width * height * 4;i += 4)
3531                 {
3532                         if (skindata[i] < 255)
3533                         {
3534                                 skinframe->hasalpha = true;
3535                                 break;
3536                         }
3537                 }
3538                 if (r_loadfog && skinframe->hasalpha)
3539                 {
3540                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3541                         memcpy(fogpixels, skindata, width * height * 4);
3542                         for (i = 0;i < width * height * 4;i += 4)
3543                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3544                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3545                         Mem_Free(fogpixels);
3546                 }
3547         }
3548
3549         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3550         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3551
3552         return skinframe;
3553 }
3554
3555 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3556 {
3557         int i;
3558         int featuresmask;
3559         skinframe_t *skinframe;
3560
3561         if (cls.state == ca_dedicated)
3562                 return NULL;
3563
3564         // if already loaded just return it, otherwise make a new skinframe
3565         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3566         if (skinframe->base)
3567                 return skinframe;
3568         //textureflags &= ~TEXF_FORCE_RELOAD;
3569
3570         skinframe->stain = NULL;
3571         skinframe->merged = NULL;
3572         skinframe->base = NULL;
3573         skinframe->pants = NULL;
3574         skinframe->shirt = NULL;
3575         skinframe->nmap = NULL;
3576         skinframe->gloss = NULL;
3577         skinframe->glow = NULL;
3578         skinframe->fog = NULL;
3579         skinframe->reflect = NULL;
3580         skinframe->hasalpha = false;
3581
3582         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3583         if (!skindata)
3584                 return NULL;
3585
3586         if (developer_loading.integer)
3587                 Con_Printf("loading quake skin \"%s\"\n", name);
3588
3589         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3590         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3591         memcpy(skinframe->qpixels, skindata, width*height);
3592         skinframe->qwidth = width;
3593         skinframe->qheight = height;
3594
3595         featuresmask = 0;
3596         for (i = 0;i < width * height;i++)
3597                 featuresmask |= palette_featureflags[skindata[i]];
3598
3599         skinframe->hasalpha = false;
3600         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3601         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3602         skinframe->qgeneratemerged = true;
3603         skinframe->qgeneratebase = skinframe->qhascolormapping;
3604         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3605
3606         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3607         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3608
3609         return skinframe;
3610 }
3611
3612 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3613 {
3614         int width;
3615         int height;
3616         unsigned char *skindata;
3617         char vabuf[1024];
3618
3619         if (!skinframe->qpixels)
3620                 return;
3621
3622         if (!skinframe->qhascolormapping)
3623                 colormapped = false;
3624
3625         if (colormapped)
3626         {
3627                 if (!skinframe->qgeneratebase)
3628                         return;
3629         }
3630         else
3631         {
3632                 if (!skinframe->qgeneratemerged)
3633                         return;
3634         }
3635
3636         width = skinframe->qwidth;
3637         height = skinframe->qheight;
3638         skindata = skinframe->qpixels;
3639
3640         if (skinframe->qgeneratenmap)
3641         {
3642                 unsigned char *temp1, *temp2;
3643                 skinframe->qgeneratenmap = false;
3644                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3645                 temp2 = temp1 + width * height * 4;
3646                 // use either a custom palette or the quake palette
3647                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3648                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3649                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3650                 Mem_Free(temp1);
3651         }
3652
3653         if (skinframe->qgenerateglow)
3654         {
3655                 skinframe->qgenerateglow = false;
3656                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3657         }
3658
3659         if (colormapped)
3660         {
3661                 skinframe->qgeneratebase = false;
3662                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3663                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3664                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3665         }
3666         else
3667         {
3668                 skinframe->qgeneratemerged = false;
3669                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3670         }
3671
3672         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3673         {
3674                 Mem_Free(skinframe->qpixels);
3675                 skinframe->qpixels = NULL;
3676         }
3677 }
3678
3679 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3680 {
3681         int i;
3682         skinframe_t *skinframe;
3683         char vabuf[1024];
3684
3685         if (cls.state == ca_dedicated)
3686                 return NULL;
3687
3688         // if already loaded just return it, otherwise make a new skinframe
3689         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3690         if (skinframe->base)
3691                 return skinframe;
3692         textureflags &= ~TEXF_FORCE_RELOAD;
3693
3694         skinframe->stain = NULL;
3695         skinframe->merged = NULL;
3696         skinframe->base = NULL;
3697         skinframe->pants = NULL;
3698         skinframe->shirt = NULL;
3699         skinframe->nmap = NULL;
3700         skinframe->gloss = NULL;
3701         skinframe->glow = NULL;
3702         skinframe->fog = NULL;
3703         skinframe->reflect = NULL;
3704         skinframe->hasalpha = false;
3705
3706         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3707         if (!skindata)
3708                 return NULL;
3709
3710         if (developer_loading.integer)
3711                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3712
3713         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3714         if (textureflags & TEXF_ALPHA)
3715         {
3716                 for (i = 0;i < width * height;i++)
3717                 {
3718                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3719                         {
3720                                 skinframe->hasalpha = true;
3721                                 break;
3722                         }
3723                 }
3724                 if (r_loadfog && skinframe->hasalpha)
3725                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3726         }
3727
3728         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3729         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3730
3731         return skinframe;
3732 }
3733
3734 skinframe_t *R_SkinFrame_LoadMissing(void)
3735 {
3736         skinframe_t *skinframe;
3737
3738         if (cls.state == ca_dedicated)
3739                 return NULL;
3740
3741         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3742         skinframe->stain = NULL;
3743         skinframe->merged = NULL;
3744         skinframe->base = NULL;
3745         skinframe->pants = NULL;
3746         skinframe->shirt = NULL;
3747         skinframe->nmap = NULL;
3748         skinframe->gloss = NULL;
3749         skinframe->glow = NULL;
3750         skinframe->fog = NULL;
3751         skinframe->reflect = NULL;
3752         skinframe->hasalpha = false;
3753
3754         skinframe->avgcolor[0] = rand() / RAND_MAX;
3755         skinframe->avgcolor[1] = rand() / RAND_MAX;
3756         skinframe->avgcolor[2] = rand() / RAND_MAX;
3757         skinframe->avgcolor[3] = 1;
3758
3759         return skinframe;
3760 }
3761
3762 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3763 typedef struct suffixinfo_s
3764 {
3765         const char *suffix;
3766         qboolean flipx, flipy, flipdiagonal;
3767 }
3768 suffixinfo_t;
3769 static suffixinfo_t suffix[3][6] =
3770 {
3771         {
3772                 {"px",   false, false, false},
3773                 {"nx",   false, false, false},
3774                 {"py",   false, false, false},
3775                 {"ny",   false, false, false},
3776                 {"pz",   false, false, false},
3777                 {"nz",   false, false, false}
3778         },
3779         {
3780                 {"posx", false, false, false},
3781                 {"negx", false, false, false},
3782                 {"posy", false, false, false},
3783                 {"negy", false, false, false},
3784                 {"posz", false, false, false},
3785                 {"negz", false, false, false}
3786         },
3787         {
3788                 {"rt",    true, false,  true},
3789                 {"lf",   false,  true,  true},
3790                 {"ft",    true,  true, false},
3791                 {"bk",   false, false, false},
3792                 {"up",    true, false,  true},
3793                 {"dn",    true, false,  true}
3794         }
3795 };
3796
3797 static int componentorder[4] = {0, 1, 2, 3};
3798
3799 static rtexture_t *R_LoadCubemap(const char *basename)
3800 {
3801         int i, j, cubemapsize;
3802         unsigned char *cubemappixels, *image_buffer;
3803         rtexture_t *cubemaptexture;
3804         char name[256];
3805         // must start 0 so the first loadimagepixels has no requested width/height
3806         cubemapsize = 0;
3807         cubemappixels = NULL;
3808         cubemaptexture = NULL;
3809         // keep trying different suffix groups (posx, px, rt) until one loads
3810         for (j = 0;j < 3 && !cubemappixels;j++)
3811         {
3812                 // load the 6 images in the suffix group
3813                 for (i = 0;i < 6;i++)
3814                 {
3815                         // generate an image name based on the base and and suffix
3816                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3817                         // load it
3818                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3819                         {
3820                                 // an image loaded, make sure width and height are equal
3821                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3822                                 {
3823                                         // if this is the first image to load successfully, allocate the cubemap memory
3824                                         if (!cubemappixels && image_width >= 1)
3825                                         {
3826                                                 cubemapsize = image_width;
3827                                                 // note this clears to black, so unavailable sides are black
3828                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3829                                         }
3830                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3831                                         if (cubemappixels)
3832                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3833                                 }
3834                                 else
3835                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3836                                 // free the image
3837                                 Mem_Free(image_buffer);
3838                         }
3839                 }
3840         }
3841         // if a cubemap loaded, upload it
3842         if (cubemappixels)
3843         {
3844                 if (developer_loading.integer)
3845                         Con_Printf("loading cubemap \"%s\"\n", basename);
3846
3847                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3848                 Mem_Free(cubemappixels);
3849         }
3850         else
3851         {
3852                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3853                 if (developer_loading.integer)
3854                 {
3855                         Con_Printf("(tried tried images ");
3856                         for (j = 0;j < 3;j++)
3857                                 for (i = 0;i < 6;i++)
3858                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3859                         Con_Print(" and was unable to find any of them).\n");
3860                 }
3861         }
3862         return cubemaptexture;
3863 }
3864
3865 rtexture_t *R_GetCubemap(const char *basename)
3866 {
3867         int i;
3868         for (i = 0;i < r_texture_numcubemaps;i++)
3869                 if (r_texture_cubemaps[i] != NULL)
3870                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3871                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3872         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3873                 return r_texture_whitecube;
3874         r_texture_numcubemaps++;
3875         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3876         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3877         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3878         return r_texture_cubemaps[i]->texture;
3879 }
3880
3881 static void R_Main_FreeViewCache(void)
3882 {
3883         if (r_refdef.viewcache.entityvisible)
3884                 Mem_Free(r_refdef.viewcache.entityvisible);
3885         if (r_refdef.viewcache.world_pvsbits)
3886                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3887         if (r_refdef.viewcache.world_leafvisible)
3888                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3889         if (r_refdef.viewcache.world_surfacevisible)
3890                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3891         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3892 }
3893
3894 static void R_Main_ResizeViewCache(void)
3895 {
3896         int numentities = r_refdef.scene.numentities;
3897         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3898         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3899         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3900         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3901         if (r_refdef.viewcache.maxentities < numentities)
3902         {
3903                 r_refdef.viewcache.maxentities = numentities;
3904                 if (r_refdef.viewcache.entityvisible)
3905                         Mem_Free(r_refdef.viewcache.entityvisible);
3906                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3907         }
3908         if (r_refdef.viewcache.world_numclusters != numclusters)
3909         {
3910                 r_refdef.viewcache.world_numclusters = numclusters;
3911                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3912                 if (r_refdef.viewcache.world_pvsbits)
3913                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3914                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3915         }
3916         if (r_refdef.viewcache.world_numleafs != numleafs)
3917         {
3918                 r_refdef.viewcache.world_numleafs = numleafs;
3919                 if (r_refdef.viewcache.world_leafvisible)
3920                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3921                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3922         }
3923         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3924         {
3925                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3926                 if (r_refdef.viewcache.world_surfacevisible)
3927                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3928                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3929         }
3930 }
3931
3932 extern rtexture_t *loadingscreentexture;
3933 static void gl_main_start(void)
3934 {
3935         loadingscreentexture = NULL;
3936         r_texture_blanknormalmap = NULL;
3937         r_texture_white = NULL;
3938         r_texture_grey128 = NULL;
3939         r_texture_black = NULL;
3940         r_texture_whitecube = NULL;
3941         r_texture_normalizationcube = NULL;
3942         r_texture_fogattenuation = NULL;
3943         r_texture_fogheighttexture = NULL;
3944         r_texture_gammaramps = NULL;
3945         r_texture_numcubemaps = 0;
3946
3947         r_loaddds = r_texture_dds_load.integer != 0;
3948         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3949
3950         switch(vid.renderpath)
3951         {
3952         case RENDERPATH_GL20:
3953         case RENDERPATH_D3D9:
3954         case RENDERPATH_D3D10:
3955         case RENDERPATH_D3D11:
3956         case RENDERPATH_SOFT:
3957         case RENDERPATH_GLES2:
3958                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3959                 Cvar_SetValueQuick(&gl_combine, 1);
3960                 Cvar_SetValueQuick(&r_glsl, 1);
3961                 r_loadnormalmap = true;
3962                 r_loadgloss = true;
3963                 r_loadfog = false;
3964                 break;
3965         case RENDERPATH_GL13:
3966         case RENDERPATH_GLES1:
3967                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3968                 Cvar_SetValueQuick(&gl_combine, 1);
3969                 Cvar_SetValueQuick(&r_glsl, 0);
3970                 r_loadnormalmap = false;
3971                 r_loadgloss = false;
3972                 r_loadfog = true;
3973                 break;
3974         case RENDERPATH_GL11:
3975                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3976                 Cvar_SetValueQuick(&gl_combine, 0);
3977                 Cvar_SetValueQuick(&r_glsl, 0);
3978                 r_loadnormalmap = false;
3979                 r_loadgloss = false;
3980                 r_loadfog = true;
3981                 break;
3982         }
3983
3984         R_AnimCache_Free();
3985         R_FrameData_Reset();
3986
3987         r_numqueries = 0;
3988         r_maxqueries = 0;
3989         memset(r_queries, 0, sizeof(r_queries));
3990
3991         r_qwskincache = NULL;
3992         r_qwskincache_size = 0;
3993
3994         // due to caching of texture_t references, the collision cache must be reset
3995         Collision_Cache_Reset(true);
3996
3997         // set up r_skinframe loading system for textures
3998         memset(&r_skinframe, 0, sizeof(r_skinframe));
3999         r_skinframe.loadsequence = 1;
4000         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4001
4002         r_main_texturepool = R_AllocTexturePool();
4003         R_BuildBlankTextures();
4004         R_BuildNoTexture();
4005         if (vid.support.arb_texture_cube_map)
4006         {
4007                 R_BuildWhiteCube();
4008                 R_BuildNormalizationCube();
4009         }
4010         r_texture_fogattenuation = NULL;
4011         r_texture_fogheighttexture = NULL;
4012         r_texture_gammaramps = NULL;
4013         //r_texture_fogintensity = NULL;
4014         memset(&r_fb, 0, sizeof(r_fb));
4015         r_glsl_permutation = NULL;
4016         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4017         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4018         glslshaderstring = NULL;
4019 #ifdef SUPPORTD3D
4020         r_hlsl_permutation = NULL;
4021         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4022         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4023 #endif
4024         hlslshaderstring = NULL;
4025         memset(&r_svbsp, 0, sizeof (r_svbsp));
4026
4027         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4028         r_texture_numcubemaps = 0;
4029
4030         r_refdef.fogmasktable_density = 0;
4031 }
4032
4033 static void gl_main_shutdown(void)
4034 {
4035         R_AnimCache_Free();
4036         R_FrameData_Reset();
4037
4038         R_Main_FreeViewCache();
4039
4040         switch(vid.renderpath)
4041         {
4042         case RENDERPATH_GL11:
4043         case RENDERPATH_GL13:
4044         case RENDERPATH_GL20:
4045         case RENDERPATH_GLES1:
4046         case RENDERPATH_GLES2:
4047 #ifdef GL_SAMPLES_PASSED_ARB
4048                 if (r_maxqueries)
4049                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4050 #endif
4051                 break;
4052         case RENDERPATH_D3D9:
4053                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4054                 break;
4055         case RENDERPATH_D3D10:
4056                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4057                 break;
4058         case RENDERPATH_D3D11:
4059                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4060                 break;
4061         case RENDERPATH_SOFT:
4062                 break;
4063         }
4064
4065         r_numqueries = 0;
4066         r_maxqueries = 0;
4067         memset(r_queries, 0, sizeof(r_queries));
4068
4069         r_qwskincache = NULL;
4070         r_qwskincache_size = 0;
4071
4072         // clear out the r_skinframe state
4073         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4074         memset(&r_skinframe, 0, sizeof(r_skinframe));
4075
4076         if (r_svbsp.nodes)
4077                 Mem_Free(r_svbsp.nodes);
4078         memset(&r_svbsp, 0, sizeof (r_svbsp));
4079         R_FreeTexturePool(&r_main_texturepool);
4080         loadingscreentexture = NULL;
4081         r_texture_blanknormalmap = NULL;
4082         r_texture_white = NULL;
4083         r_texture_grey128 = NULL;
4084         r_texture_black = NULL;
4085         r_texture_whitecube = NULL;
4086         r_texture_normalizationcube = NULL;
4087         r_texture_fogattenuation = NULL;
4088         r_texture_fogheighttexture = NULL;
4089         r_texture_gammaramps = NULL;
4090         r_texture_numcubemaps = 0;
4091         //r_texture_fogintensity = NULL;
4092         memset(&r_fb, 0, sizeof(r_fb));
4093         R_GLSL_Restart_f();
4094
4095         r_glsl_permutation = NULL;
4096         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4097         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4098         glslshaderstring = NULL;
4099 #ifdef SUPPORTD3D
4100         r_hlsl_permutation = NULL;
4101         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4102         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4103 #endif
4104         hlslshaderstring = NULL;
4105 }
4106
4107 static void gl_main_newmap(void)
4108 {
4109         // FIXME: move this code to client
4110         char *entities, entname[MAX_QPATH];
4111         if (r_qwskincache)
4112                 Mem_Free(r_qwskincache);
4113         r_qwskincache = NULL;
4114         r_qwskincache_size = 0;
4115         if (cl.worldmodel)
4116         {
4117                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4118                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4119                 {
4120                         CL_ParseEntityLump(entities);
4121                         Mem_Free(entities);
4122                         return;
4123                 }
4124                 if (cl.worldmodel->brush.entities)
4125                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4126         }
4127         R_Main_FreeViewCache();
4128
4129         R_FrameData_Reset();
4130 }
4131
4132 void GL_Main_Init(void)
4133 {
4134         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4135
4136         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4137         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4138         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4139         if (gamemode == GAME_NEHAHRA)
4140         {
4141                 Cvar_RegisterVariable (&gl_fogenable);
4142                 Cvar_RegisterVariable (&gl_fogdensity);
4143                 Cvar_RegisterVariable (&gl_fogred);
4144                 Cvar_RegisterVariable (&gl_foggreen);
4145                 Cvar_RegisterVariable (&gl_fogblue);
4146                 Cvar_RegisterVariable (&gl_fogstart);
4147                 Cvar_RegisterVariable (&gl_fogend);
4148                 Cvar_RegisterVariable (&gl_skyclip);
4149         }
4150         Cvar_RegisterVariable(&r_motionblur);
4151         Cvar_RegisterVariable(&r_damageblur);
4152         Cvar_RegisterVariable(&r_motionblur_averaging);
4153         Cvar_RegisterVariable(&r_motionblur_randomize);
4154         Cvar_RegisterVariable(&r_motionblur_minblur);
4155         Cvar_RegisterVariable(&r_motionblur_maxblur);
4156         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4157         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4158         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4159         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4160         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4161         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4162         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4163         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4164         Cvar_RegisterVariable(&r_equalize_entities_by);
4165         Cvar_RegisterVariable(&r_equalize_entities_to);
4166         Cvar_RegisterVariable(&r_depthfirst);
4167         Cvar_RegisterVariable(&r_useinfinitefarclip);
4168         Cvar_RegisterVariable(&r_farclip_base);
4169         Cvar_RegisterVariable(&r_farclip_world);
4170         Cvar_RegisterVariable(&r_nearclip);
4171         Cvar_RegisterVariable(&r_deformvertexes);
4172         Cvar_RegisterVariable(&r_transparent);
4173         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4174         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4175         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4176         Cvar_RegisterVariable(&r_showoverdraw);
4177         Cvar_RegisterVariable(&r_showbboxes);
4178         Cvar_RegisterVariable(&r_showsurfaces);
4179         Cvar_RegisterVariable(&r_showtris);
4180         Cvar_RegisterVariable(&r_shownormals);
4181         Cvar_RegisterVariable(&r_showlighting);
4182         Cvar_RegisterVariable(&r_showshadowvolumes);
4183         Cvar_RegisterVariable(&r_showcollisionbrushes);
4184         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4185         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4186         Cvar_RegisterVariable(&r_showdisabledepthtest);
4187         Cvar_RegisterVariable(&r_drawportals);
4188         Cvar_RegisterVariable(&r_drawentities);
4189         Cvar_RegisterVariable(&r_draw2d);
4190         Cvar_RegisterVariable(&r_drawworld);
4191         Cvar_RegisterVariable(&r_cullentities_trace);
4192         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4193         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4194         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4195         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4196         Cvar_RegisterVariable(&r_sortentities);
4197         Cvar_RegisterVariable(&r_drawviewmodel);
4198         Cvar_RegisterVariable(&r_drawexteriormodel);
4199         Cvar_RegisterVariable(&r_speeds);
4200         Cvar_RegisterVariable(&r_fullbrights);
4201         Cvar_RegisterVariable(&r_wateralpha);
4202         Cvar_RegisterVariable(&r_dynamic);
4203         Cvar_RegisterVariable(&r_fakelight);
4204         Cvar_RegisterVariable(&r_fakelight_intensity);
4205         Cvar_RegisterVariable(&r_fullbright);
4206         Cvar_RegisterVariable(&r_shadows);
4207         Cvar_RegisterVariable(&r_shadows_darken);
4208         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4209         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4210         Cvar_RegisterVariable(&r_shadows_throwdistance);
4211         Cvar_RegisterVariable(&r_shadows_throwdirection);
4212         Cvar_RegisterVariable(&r_shadows_focus);
4213         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4214         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4215         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4216         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4217         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4218         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4219         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4220         Cvar_RegisterVariable(&r_fog_exp2);
4221         Cvar_RegisterVariable(&r_fog_clear);
4222         Cvar_RegisterVariable(&r_drawfog);
4223         Cvar_RegisterVariable(&r_transparentdepthmasking);
4224         Cvar_RegisterVariable(&r_transparent_sortmindist);
4225         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4226         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4227         Cvar_RegisterVariable(&r_texture_dds_load);
4228         Cvar_RegisterVariable(&r_texture_dds_save);
4229         Cvar_RegisterVariable(&r_textureunits);
4230         Cvar_RegisterVariable(&gl_combine);
4231         Cvar_RegisterVariable(&r_usedepthtextures);
4232         Cvar_RegisterVariable(&r_viewfbo);
4233         Cvar_RegisterVariable(&r_viewscale);
4234         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4235         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4236         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4237         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4238         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4239         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4240         Cvar_RegisterVariable(&r_glsl);
4241         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4242         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4243         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4244         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4245         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4246         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4247         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4248         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4249         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4250         Cvar_RegisterVariable(&r_glsl_postprocess);
4251         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4252         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4253         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4254         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4255         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4256         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4257         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4258         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4259         Cvar_RegisterVariable(&r_celshading);
4260         Cvar_RegisterVariable(&r_celoutlines);
4261
4262         Cvar_RegisterVariable(&r_water);
4263         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4264         Cvar_RegisterVariable(&r_water_clippingplanebias);
4265         Cvar_RegisterVariable(&r_water_refractdistort);
4266         Cvar_RegisterVariable(&r_water_reflectdistort);
4267         Cvar_RegisterVariable(&r_water_scissormode);
4268         Cvar_RegisterVariable(&r_water_lowquality);
4269         Cvar_RegisterVariable(&r_water_hideplayer);
4270         Cvar_RegisterVariable(&r_water_fbo);
4271
4272         Cvar_RegisterVariable(&r_lerpsprites);
4273         Cvar_RegisterVariable(&r_lerpmodels);
4274         Cvar_RegisterVariable(&r_lerplightstyles);
4275         Cvar_RegisterVariable(&r_waterscroll);
4276         Cvar_RegisterVariable(&r_bloom);
4277         Cvar_RegisterVariable(&r_bloom_colorscale);
4278         Cvar_RegisterVariable(&r_bloom_brighten);
4279         Cvar_RegisterVariable(&r_bloom_blur);
4280         Cvar_RegisterVariable(&r_bloom_resolution);
4281         Cvar_RegisterVariable(&r_bloom_colorexponent);
4282         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4283         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4284         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4285         Cvar_RegisterVariable(&r_hdr_glowintensity);
4286         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4287         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4288         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4289         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4290         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4291         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4292         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4293         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4294         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4295         Cvar_RegisterVariable(&developer_texturelogging);
4296         Cvar_RegisterVariable(&gl_lightmaps);
4297         Cvar_RegisterVariable(&r_test);
4298         Cvar_RegisterVariable(&r_batch_multidraw);
4299         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4300         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4301         Cvar_RegisterVariable(&r_glsl_skeletal);
4302         Cvar_RegisterVariable(&r_glsl_saturation);
4303         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4304         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4305         Cvar_RegisterVariable(&r_framedatasize);
4306         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4307                 Cvar_SetValue("r_fullbrights", 0);
4308         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4309 }
4310
4311 void Render_Init(void)
4312 {
4313         gl_backend_init();
4314         R_Textures_Init();
4315         GL_Main_Init();
4316         Font_Init();
4317         GL_Draw_Init();
4318         R_Shadow_Init();
4319         R_Sky_Init();
4320         GL_Surf_Init();
4321         Sbar_Init();
4322         R_Particles_Init();
4323         R_Explosion_Init();
4324         R_LightningBeams_Init();
4325         Mod_RenderInit();
4326 }
4327
4328 /*
4329 ===============
4330 GL_Init
4331 ===============
4332 */
4333 #ifndef USE_GLES2
4334 extern char *ENGINE_EXTENSIONS;
4335 void GL_Init (void)
4336 {
4337         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4338         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4339         gl_version = (const char *)qglGetString(GL_VERSION);
4340         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4341
4342         if (!gl_extensions)
4343                 gl_extensions = "";
4344         if (!gl_platformextensions)
4345                 gl_platformextensions = "";
4346
4347         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4348         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4349         Con_Printf("GL_VERSION: %s\n", gl_version);
4350         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4351         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4352
4353         VID_CheckExtensions();
4354
4355         // LordHavoc: report supported extensions
4356         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4357
4358         // clear to black (loading plaque will be seen over this)
4359         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4360 }
4361 #endif
4362
4363 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4364 {
4365         int i;
4366         mplane_t *p;
4367         if (r_trippy.integer)
4368                 return false;
4369         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4370         {
4371                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4372                 if (i == 4)
4373                         continue;
4374                 p = r_refdef.view.frustum + i;
4375                 switch(p->signbits)
4376                 {
4377                 default:
4378                 case 0:
4379                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4380                                 return true;
4381                         break;
4382                 case 1:
4383                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4384                                 return true;
4385                         break;
4386                 case 2:
4387                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4388                                 return true;
4389                         break;
4390                 case 3:
4391                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4392                                 return true;
4393                         break;
4394                 case 4:
4395                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4396                                 return true;
4397                         break;
4398                 case 5:
4399                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4400                                 return true;
4401                         break;
4402                 case 6:
4403                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4404                                 return true;
4405                         break;
4406                 case 7:
4407                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4408                                 return true;
4409                         break;
4410                 }
4411         }
4412         return false;
4413 }
4414
4415 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4416 {
4417         int i;
4418         const mplane_t *p;
4419         if (r_trippy.integer)
4420                 return false;
4421         for (i = 0;i < numplanes;i++)
4422         {
4423                 p = planes + i;
4424                 switch(p->signbits)
4425                 {
4426                 default:
4427                 case 0:
4428                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4429                                 return true;
4430                         break;
4431                 case 1:
4432                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4433                                 return true;
4434                         break;
4435                 case 2:
4436                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4437                                 return true;
4438                         break;
4439                 case 3:
4440                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 4:
4444                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 case 5:
4448                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 case 6:
4452                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 case 7:
4456                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 }
4460         }
4461         return false;
4462 }
4463
4464 //==================================================================================
4465
4466 // LordHavoc: this stores temporary data used within the same frame
4467
4468 typedef struct r_framedata_mem_s
4469 {
4470         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4471         size_t size; // how much usable space
4472         size_t current; // how much space in use
4473         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4474         size_t wantedsize; // how much space was allocated
4475         unsigned char *data; // start of real data (16byte aligned)
4476 }
4477 r_framedata_mem_t;
4478
4479 static r_framedata_mem_t *r_framedata_mem;
4480
4481 void R_FrameData_Reset(void)
4482 {
4483         while (r_framedata_mem)
4484         {
4485                 r_framedata_mem_t *next = r_framedata_mem->purge;
4486                 Mem_Free(r_framedata_mem);
4487                 r_framedata_mem = next;
4488         }
4489 }
4490
4491 static void R_FrameData_Resize(void)
4492 {
4493         size_t wantedsize;
4494         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4495         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4496         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4497         {
4498                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4499                 newmem->wantedsize = wantedsize;
4500                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4501                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4502                 newmem->current = 0;
4503                 newmem->mark = 0;
4504                 newmem->purge = r_framedata_mem;
4505                 r_framedata_mem = newmem;
4506         }
4507 }
4508
4509 void R_FrameData_NewFrame(void)
4510 {
4511         R_FrameData_Resize();
4512         if (!r_framedata_mem)
4513                 return;
4514         // if we ran out of space on the last frame, free the old memory now
4515         while (r_framedata_mem->purge)
4516         {
4517                 // repeatedly remove the second item in the list, leaving only head
4518                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4519                 Mem_Free(r_framedata_mem->purge);
4520                 r_framedata_mem->purge = next;
4521         }
4522         // reset the current mem pointer
4523         r_framedata_mem->current = 0;
4524         r_framedata_mem->mark = 0;
4525 }
4526
4527 void *R_FrameData_Alloc(size_t size)
4528 {
4529         void *data;
4530
4531         // align to 16 byte boundary - the data pointer is already aligned, so we
4532         // only need to ensure the size of every allocation is also aligned
4533         size = (size + 15) & ~15;
4534
4535         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4536         {
4537                 // emergency - we ran out of space, allocate more memory
4538                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4539                 R_FrameData_Resize();
4540         }
4541
4542         data = r_framedata_mem->data + r_framedata_mem->current;
4543         r_framedata_mem->current += size;
4544
4545         // count the usage for stats
4546         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4547         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4548
4549         return (void *)data;
4550 }
4551
4552 void *R_FrameData_Store(size_t size, void *data)
4553 {
4554         void *d = R_FrameData_Alloc(size);
4555         if (d && data)
4556                 memcpy(d, data, size);
4557         return d;
4558 }
4559
4560 void R_FrameData_SetMark(void)
4561 {
4562         if (!r_framedata_mem)
4563                 return;
4564         r_framedata_mem->mark = r_framedata_mem->current;
4565 }
4566
4567 void R_FrameData_ReturnToMark(void)
4568 {
4569         if (!r_framedata_mem)
4570                 return;
4571         r_framedata_mem->current = r_framedata_mem->mark;
4572 }
4573
4574 //==================================================================================
4575
4576 // LordHavoc: animcache originally written by Echon, rewritten since then
4577
4578 /**
4579  * Animation cache prevents re-generating mesh data for an animated model
4580  * multiple times in one frame for lighting, shadowing, reflections, etc.
4581  */
4582
4583 void R_AnimCache_Free(void)
4584 {
4585 }
4586
4587 void R_AnimCache_ClearCache(void)
4588 {
4589         int i;
4590         entity_render_t *ent;
4591
4592         for (i = 0;i < r_refdef.scene.numentities;i++)
4593         {
4594                 ent = r_refdef.scene.entities[i];
4595                 ent->animcache_vertex3f = NULL;
4596                 ent->animcache_normal3f = NULL;
4597                 ent->animcache_svector3f = NULL;
4598                 ent->animcache_tvector3f = NULL;
4599                 ent->animcache_vertexmesh = NULL;
4600                 ent->animcache_vertex3fbuffer = NULL;
4601                 ent->animcache_vertexmeshbuffer = NULL;
4602                 ent->animcache_skeletaltransform3x4 = NULL;
4603         }
4604 }
4605
4606 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4607 {
4608         int i;
4609
4610         // check if we need the meshbuffers
4611         if (!vid.useinterleavedarrays)
4612                 return;
4613
4614         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4615                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4616         // TODO: upload vertex3f buffer?
4617         if (ent->animcache_vertexmesh)
4618         {
4619                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4620                 for (i = 0;i < numvertices;i++)
4621                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4622                 if (ent->animcache_svector3f)
4623                         for (i = 0;i < numvertices;i++)
4624                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4625                 if (ent->animcache_tvector3f)
4626                         for (i = 0;i < numvertices;i++)
4627                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4628                 if (ent->animcache_normal3f)
4629                         for (i = 0;i < numvertices;i++)
4630                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4631                 // TODO: upload vertexmeshbuffer?
4632         }
4633 }
4634
4635 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4636 {
4637         dp_model_t *model = ent->model;
4638         int numvertices;
4639
4640         // cache skeletal animation data first (primarily for gpu-skinning)
4641         if (!ent->animcache_skeletaltransform3x4 && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4642         {
4643                 int i;
4644                 int blends;
4645                 const skeleton_t *skeleton = ent->skeleton;
4646                 const frameblend_t *frameblend = ent->frameblend;
4647                 float *boneposerelative;
4648                 float m[12];
4649                 static float bonepose[256][12];
4650                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4651                 boneposerelative = ent->animcache_skeletaltransform3x4;
4652                 if (skeleton && !skeleton->relativetransforms)
4653                         skeleton = NULL;
4654                 // resolve hierarchy and make relative transforms (deforms) which the shader wants
4655                 if (skeleton)
4656                 {
4657                         for (i = 0;i < model->num_bones;i++)
4658                         {
4659                                 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
4660                                 if (model->data_bones[i].parent >= 0)
4661                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4662                                 else
4663                                         memcpy(bonepose[i], m, sizeof(m));
4664
4665                                 // create a relative deformation matrix to describe displacement
4666                                 // from the base mesh, which is used by the actual weighting
4667                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4668                         }
4669                 }
4670                 else
4671                 {
4672                         for (i = 0;i < model->num_bones;i++)
4673                         {
4674                                 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
4675                                 float lerp = frameblend[0].lerp,
4676                                         tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4677                                         rx = pose7s[3] * lerp,
4678                                         ry = pose7s[4] * lerp,
4679                                         rz = pose7s[5] * lerp,
4680                                         rw = pose7s[6] * lerp,
4681                                         dx = tx*rw + ty*rz - tz*ry,
4682                                         dy = -tx*rz + ty*rw + tz*rx,
4683                                         dz = tx*ry - ty*rx + tz*rw,
4684                                         dw = -tx*rx - ty*ry - tz*rz,
4685                                         scale, sx, sy, sz, sw;
4686                                 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
4687                                 {
4688                                         const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
4689                                         float lerp = frameblend[blends].lerp,
4690                                                 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4691                                                 qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
4692                                         if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
4693                                         qx *= lerp;
4694                                         qy *= lerp;
4695                                         qz *= lerp;
4696                                         qw *= lerp;
4697                                         rx += qx;
4698                                         ry += qy;
4699                                         rz += qz;
4700                                         rw += qw;
4701                                         dx += tx*qw + ty*qz - tz*qy;
4702                                         dy += -tx*qz + ty*qw + tz*qx;
4703                                         dz += tx*qy - ty*qx + tz*qw;
4704                                         dw += -tx*qx - ty*qy - tz*qz;
4705                                 }
4706                                 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
4707                                 sx = rx * scale;
4708                                 sy = ry * scale;
4709                                 sz = rz * scale;
4710                                 sw = rw * scale;
4711                                 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
4712                                 m[1] = 2*(sx*ry - sw*rz);
4713                                 m[2] = 2*(sx*rz + sw*ry);
4714                                 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
4715                                 m[4] = 2*(sx*ry + sw*rz);
4716                                 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
4717                                 m[6] = 2*(sy*rz - sw*rx);
4718                                 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
4719                                 m[8] = 2*(sx*rz - sw*ry);
4720                                 m[9] = 2*(sy*rz + sw*rx);
4721                                 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
4722                                 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
4723                                 if (i == r_skeletal_debugbone.integer)
4724                                         m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
4725                                 m[3] *= r_skeletal_debugtranslatex.value;
4726                                 m[7] *= r_skeletal_debugtranslatey.value;
4727                                 m[11] *= r_skeletal_debugtranslatez.value;
4728                                 if (model->data_bones[i].parent >= 0)
4729                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4730                                 else
4731                                         memcpy(bonepose[i], m, sizeof(m));
4732                                 // create a relative deformation matrix to describe displacement
4733                                 // from the base mesh, which is used by the actual weighting
4734                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4735                         }
4736                 }
4737         }
4738
4739         // see if it's already cached this frame
4740         if (ent->animcache_vertex3f)
4741         {
4742                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4743                 if (wantnormals || wanttangents)
4744                 {
4745                         if (ent->animcache_normal3f)
4746                                 wantnormals = false;
4747                         if (ent->animcache_svector3f)
4748                                 wanttangents = false;
4749                         if (wantnormals || wanttangents)
4750                         {
4751                                 numvertices = model->surfmesh.num_vertices;
4752                                 if (wantnormals)
4753                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4754                                 if (wanttangents)
4755                                 {
4756                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4757                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4758                                 }
4759                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4760                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4761                         }
4762                 }
4763         }
4764         else
4765         {
4766                 // see if this ent is worth caching
4767                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4768                         return false;
4769                 // skip entity if the shader backend has a cheaper way
4770                 if (model->surfmesh.data_skeletalindex4ub && r_glsl_skeletal.integer && !r_showsurfaces.integer) // FIXME add r_showsurfaces support to GLSL skeletal!
4771                 {
4772                         switch (vid.renderpath)
4773                         {
4774                         case RENDERPATH_GL20:
4775                                 return false;
4776                         case RENDERPATH_GL11:
4777                         case RENDERPATH_GL13:
4778                         case RENDERPATH_GLES1:
4779                         case RENDERPATH_GLES2:
4780                         case RENDERPATH_D3D9:
4781                         case RENDERPATH_D3D10:
4782                         case RENDERPATH_D3D11:
4783                         case RENDERPATH_SOFT:
4784                                 break;
4785                         }
4786                 }
4787                 // get some memory for this entity and generate mesh data
4788                 numvertices = model->surfmesh.num_vertices;
4789                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4790                 if (wantnormals)
4791                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4792                 if (wanttangents)
4793                 {
4794                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4795                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4796                 }
4797                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4798                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4799         }
4800         return true;
4801 }
4802
4803 void R_AnimCache_CacheVisibleEntities(void)
4804 {
4805         int i;
4806         qboolean wantnormals = true;
4807         qboolean wanttangents = !r_showsurfaces.integer;
4808
4809         switch(vid.renderpath)
4810         {
4811         case RENDERPATH_GL20:
4812         case RENDERPATH_D3D9:
4813         case RENDERPATH_D3D10:
4814         case RENDERPATH_D3D11:
4815         case RENDERPATH_GLES2:
4816                 break;
4817         case RENDERPATH_GL11:
4818         case RENDERPATH_GL13:
4819         case RENDERPATH_GLES1:
4820                 wanttangents = false;
4821                 break;
4822         case RENDERPATH_SOFT:
4823                 break;
4824         }
4825
4826         if (r_shownormals.integer)
4827                 wanttangents = wantnormals = true;
4828
4829         // TODO: thread this
4830         // NOTE: R_PrepareRTLights() also caches entities
4831
4832         for (i = 0;i < r_refdef.scene.numentities;i++)
4833                 if (r_refdef.viewcache.entityvisible[i])
4834                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4835 }
4836
4837 //==================================================================================
4838
4839 extern cvar_t r_overheadsprites_pushback;
4840
4841 static void R_View_UpdateEntityLighting (void)
4842 {
4843         int i;
4844         entity_render_t *ent;
4845         vec3_t tempdiffusenormal, avg;
4846         vec_t f, fa, fd, fdd;
4847         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4848
4849         for (i = 0;i < r_refdef.scene.numentities;i++)
4850         {
4851                 ent = r_refdef.scene.entities[i];
4852
4853                 // skip unseen models
4854                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4855                         continue;
4856
4857                 // skip bsp models
4858                 if (ent->model && ent->model == cl.worldmodel)
4859                 {
4860                         // TODO: use modellight for r_ambient settings on world?
4861                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4862                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4863                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4864                         continue;
4865                 }
4866                 
4867                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4868                 {
4869                         // aleady updated by CSQC
4870                         // TODO: force modellight on BSP models in this case?
4871                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4872                 }
4873                 else
4874                 {
4875                         // fetch the lighting from the worldmodel data
4876                         VectorClear(ent->modellight_ambient);
4877                         VectorClear(ent->modellight_diffuse);
4878                         VectorClear(tempdiffusenormal);
4879                         if (ent->flags & RENDER_LIGHT)
4880                         {
4881                                 vec3_t org;
4882                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4883
4884                                 // complete lightning for lit sprites
4885                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4886                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4887                                 {
4888                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4889                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4890                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4891                                 }
4892                                 else
4893                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4894
4895                                 if(ent->flags & RENDER_EQUALIZE)
4896                                 {
4897                                         // first fix up ambient lighting...
4898                                         if(r_equalize_entities_minambient.value > 0)
4899                                         {
4900                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4901                                                 if(fd > 0)
4902                                                 {
4903                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4904                                                         if(fa < r_equalize_entities_minambient.value * fd)
4905                                                         {
4906                                                                 // solve:
4907                                                                 //   fa'/fd' = minambient
4908                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4909                                                                 //   ...
4910                                                                 //   fa' = fd' * minambient
4911                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4912                                                                 //   ...
4913                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4914                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4915                                                                 //   ...
4916                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4917                                                                 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
4918                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4919                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4920                                                         }
4921                                                 }
4922                                         }
4923
4924                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4925                                         {
4926                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4927                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4928                                                 f = fa + 0.25 * fd;
4929                                                 if(f > 0)
4930                                                 {
4931                                                         // adjust brightness and saturation to target
4932                                                         avg[0] = avg[1] = avg[2] = fa / f;
4933                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4934                                                         avg[0] = avg[1] = avg[2] = fd / f;
4935                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4936                                                 }
4937                                         }
4938                                 }
4939                         }
4940                         else // highly rare
4941                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4942                 }
4943
4944                 // move the light direction into modelspace coordinates for lighting code
4945                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4946                 if(VectorLength2(ent->modellight_lightdir) == 0)
4947                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4948                 VectorNormalize(ent->modellight_lightdir);
4949         }
4950 }
4951
4952 #define MAX_LINEOFSIGHTTRACES 64
4953
4954 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4955 {
4956         int i;
4957         vec3_t boxmins, boxmaxs;
4958         vec3_t start;
4959         vec3_t end;
4960         dp_model_t *model = r_refdef.scene.worldmodel;
4961
4962         if (!model || !model->brush.TraceLineOfSight)
4963                 return true;
4964
4965         // expand the box a little
4966         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4967         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4968         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4969         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4970         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4971         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4972
4973         // return true if eye is inside enlarged box
4974         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4975                 return true;
4976
4977         // try center
4978         VectorCopy(eye, start);
4979         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4980         if (model->brush.TraceLineOfSight(model, start, end))
4981                 return true;
4982
4983         // try various random positions
4984         for (i = 0;i < numsamples;i++)
4985         {
4986                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4987                 if (model->brush.TraceLineOfSight(model, start, end))
4988                         return true;
4989         }
4990
4991         return false;
4992 }
4993
4994
4995 static void R_View_UpdateEntityVisible (void)
4996 {
4997         int i;
4998         int renderimask;
4999         int samples;
5000         entity_render_t *ent;
5001
5002         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5003                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5004                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5005                 :                                                          RENDER_EXTERIORMODEL;
5006         if (!r_drawviewmodel.integer)
5007                 renderimask |= RENDER_VIEWMODEL;
5008         if (!r_drawexteriormodel.integer)
5009                 renderimask |= RENDER_EXTERIORMODEL;
5010         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5011         {
5012                 // worldmodel can check visibility
5013                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5014                 for (i = 0;i < r_refdef.scene.numentities;i++)
5015                 {
5016                         ent = r_refdef.scene.entities[i];
5017                         if (!(ent->flags & renderimask))
5018                         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)))
5019                         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))
5020                                 r_refdef.viewcache.entityvisible[i] = true;
5021                 }
5022         }
5023         else
5024         {
5025                 // no worldmodel or it can't check visibility
5026                 for (i = 0;i < r_refdef.scene.numentities;i++)
5027                 {
5028                         ent = r_refdef.scene.entities[i];
5029                         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));
5030                 }
5031         }
5032         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5033                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5034         {
5035                 for (i = 0;i < r_refdef.scene.numentities;i++)
5036                 {
5037                         if (!r_refdef.viewcache.entityvisible[i])
5038                                 continue;
5039                         ent = r_refdef.scene.entities[i];
5040                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5041                         {
5042                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5043                                 if (samples < 0)
5044                                         continue; // temp entities do pvs only
5045                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5046                                         ent->last_trace_visibility = realtime;
5047                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5048                                         r_refdef.viewcache.entityvisible[i] = 0;
5049                         }
5050                 }
5051         }
5052 }
5053
5054 /// only used if skyrendermasked, and normally returns false
5055 static int R_DrawBrushModelsSky (void)
5056 {
5057         int i, sky;
5058         entity_render_t *ent;
5059
5060         sky = false;
5061         for (i = 0;i < r_refdef.scene.numentities;i++)
5062         {
5063                 if (!r_refdef.viewcache.entityvisible[i])
5064                         continue;
5065                 ent = r_refdef.scene.entities[i];
5066                 if (!ent->model || !ent->model->DrawSky)
5067                         continue;
5068                 ent->model->DrawSky(ent);
5069                 sky = true;
5070         }
5071         return sky;
5072 }
5073
5074 static void R_DrawNoModel(entity_render_t *ent);
5075 static void R_DrawModels(void)
5076 {
5077         int i;
5078         entity_render_t *ent;
5079
5080         for (i = 0;i < r_refdef.scene.numentities;i++)
5081         {
5082                 if (!r_refdef.viewcache.entityvisible[i])
5083                         continue;
5084                 ent = r_refdef.scene.entities[i];
5085                 r_refdef.stats.entities++;
5086                 /*
5087                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5088                 {
5089                         vec3_t f, l, u, o;
5090                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5091                         Con_Printf("R_DrawModels\n");
5092                         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]);
5093                         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);
5094                         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);
5095                 }
5096                 */
5097                 if (ent->model && ent->model->Draw != NULL)
5098                         ent->model->Draw(ent);
5099                 else
5100                         R_DrawNoModel(ent);
5101         }
5102 }
5103
5104 static void R_DrawModelsDepth(void)
5105 {
5106         int i;
5107         entity_render_t *ent;
5108
5109         for (i = 0;i < r_refdef.scene.numentities;i++)
5110         {
5111                 if (!r_refdef.viewcache.entityvisible[i])
5112                         continue;
5113                 ent = r_refdef.scene.entities[i];
5114                 if (ent->model && ent->model->DrawDepth != NULL)
5115                         ent->model->DrawDepth(ent);
5116         }
5117 }
5118
5119 static void R_DrawModelsDebug(void)
5120 {
5121         int i;
5122         entity_render_t *ent;
5123
5124         for (i = 0;i < r_refdef.scene.numentities;i++)
5125         {
5126                 if (!r_refdef.viewcache.entityvisible[i])
5127                         continue;
5128                 ent = r_refdef.scene.entities[i];
5129                 if (ent->model && ent->model->DrawDebug != NULL)
5130                         ent->model->DrawDebug(ent);
5131         }
5132 }
5133
5134 static void R_DrawModelsAddWaterPlanes(void)
5135 {
5136         int i;
5137         entity_render_t *ent;
5138
5139         for (i = 0;i < r_refdef.scene.numentities;i++)
5140         {
5141                 if (!r_refdef.viewcache.entityvisible[i])
5142                         continue;
5143                 ent = r_refdef.scene.entities[i];
5144                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5145                         ent->model->DrawAddWaterPlanes(ent);
5146         }
5147 }
5148
5149 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}};
5150
5151 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5152 {
5153         if (r_hdr_irisadaptation.integer)
5154         {
5155                 vec3_t p;
5156                 vec3_t ambient;
5157                 vec3_t diffuse;
5158                 vec3_t diffusenormal;
5159                 vec3_t forward;
5160                 vec_t brightness = 0.0f;
5161                 vec_t goal;
5162                 vec_t current;
5163                 vec_t d;
5164                 int c;
5165                 VectorCopy(r_refdef.view.forward, forward);
5166                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5167                 {
5168                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5169                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5170                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5171                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5172                         d = DotProduct(forward, diffusenormal);
5173                         brightness += VectorLength(ambient);
5174                         if (d > 0)
5175                                 brightness += d * VectorLength(diffuse);
5176                 }
5177                 brightness *= 1.0f / c;
5178                 brightness += 0.00001f; // make sure it's never zero
5179                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5180                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5181                 current = r_hdr_irisadaptation_value.value;
5182                 if (current < goal)
5183                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5184                 else if (current > goal)
5185                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5186                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5187                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5188         }
5189         else if (r_hdr_irisadaptation_value.value != 1.0f)
5190                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5191 }
5192
5193 static void R_View_SetFrustum(const int *scissor)
5194 {
5195         int i;
5196         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5197         vec3_t forward, left, up, origin, v;
5198
5199         if(scissor)
5200         {
5201                 // flipped x coordinates (because x points left here)
5202                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5203                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5204
5205                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5206                 switch(vid.renderpath)
5207                 {
5208                         case RENDERPATH_D3D9:
5209                         case RENDERPATH_D3D10:
5210                         case RENDERPATH_D3D11:
5211                                 // non-flipped y coordinates
5212                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5213                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5214                                 break;
5215                         case RENDERPATH_SOFT:
5216                         case RENDERPATH_GL11:
5217                         case RENDERPATH_GL13:
5218                         case RENDERPATH_GL20:
5219                         case RENDERPATH_GLES1:
5220                         case RENDERPATH_GLES2:
5221                                 // non-flipped y coordinates
5222                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5223                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5224                                 break;
5225                 }
5226         }
5227
5228         // we can't trust r_refdef.view.forward and friends in reflected scenes
5229         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5230
5231 #if 0
5232         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5233         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5234         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5235         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5236         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5237         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5238         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5239         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5240         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5241         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5242         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5243         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5244 #endif
5245
5246 #if 0
5247         zNear = r_refdef.nearclip;
5248         nudge = 1.0 - 1.0 / (1<<23);
5249         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5250         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5251         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5252         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5253         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5254         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5255         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5256         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5257 #endif
5258
5259
5260
5261 #if 0
5262         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5263         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5264         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5265         r_refdef.view.frustum[0].dist = m[15] - m[12];
5266
5267         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5268         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5269         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5270         r_refdef.view.frustum[1].dist = m[15] + m[12];
5271
5272         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5273         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5274         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5275         r_refdef.view.frustum[2].dist = m[15] - m[13];
5276
5277         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5278         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5279         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5280         r_refdef.view.frustum[3].dist = m[15] + m[13];
5281
5282         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5283         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5284         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5285         r_refdef.view.frustum[4].dist = m[15] - m[14];
5286
5287         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5288         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5289         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5290         r_refdef.view.frustum[5].dist = m[15] + m[14];
5291 #endif
5292
5293         if (r_refdef.view.useperspective)
5294         {
5295                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5296                 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]);
5297                 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]);
5298                 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]);
5299                 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]);
5300
5301                 // then the normals from the corners relative to origin
5302                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5303                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5304                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5305                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5306
5307                 // in a NORMAL view, forward cross left == up
5308                 // in a REFLECTED view, forward cross left == down
5309                 // so our cross products above need to be adjusted for a left handed coordinate system
5310                 CrossProduct(forward, left, v);
5311                 if(DotProduct(v, up) < 0)
5312                 {
5313                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5314                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5315                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5316                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5317                 }
5318
5319                 // Leaving those out was a mistake, those were in the old code, and they
5320                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5321                 // I couldn't reproduce it after adding those normalizations. --blub
5322                 VectorNormalize(r_refdef.view.frustum[0].normal);
5323                 VectorNormalize(r_refdef.view.frustum[1].normal);
5324                 VectorNormalize(r_refdef.view.frustum[2].normal);
5325                 VectorNormalize(r_refdef.view.frustum[3].normal);
5326
5327                 // make the corners absolute
5328                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5329                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5330                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5331                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5332
5333                 // one more normal
5334                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5335
5336                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5337                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5338                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5339                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5340                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5341         }
5342         else
5343         {
5344                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5345                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5346                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5347                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5348                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5349                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5350                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5351                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5352                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5353                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5354         }
5355         r_refdef.view.numfrustumplanes = 5;
5356
5357         if (r_refdef.view.useclipplane)
5358         {
5359                 r_refdef.view.numfrustumplanes = 6;
5360                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5361         }
5362
5363         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5364                 PlaneClassify(r_refdef.view.frustum + i);
5365
5366         // LordHavoc: note to all quake engine coders, Quake had a special case
5367         // for 90 degrees which assumed a square view (wrong), so I removed it,
5368         // Quake2 has it disabled as well.
5369
5370         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5371         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5372         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5373         //PlaneClassify(&frustum[0]);
5374
5375         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5376         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5377         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5378         //PlaneClassify(&frustum[1]);
5379
5380         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5381         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5382         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5383         //PlaneClassify(&frustum[2]);
5384
5385         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5386         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5387         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5388         //PlaneClassify(&frustum[3]);
5389
5390         // nearclip plane
5391         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5392         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5393         //PlaneClassify(&frustum[4]);
5394 }
5395
5396 static void R_View_UpdateWithScissor(const int *myscissor)
5397 {
5398         R_Main_ResizeViewCache();
5399         R_View_SetFrustum(myscissor);
5400         R_View_WorldVisibility(r_refdef.view.useclipplane);
5401         R_View_UpdateEntityVisible();
5402         R_View_UpdateEntityLighting();
5403 }
5404
5405 static void R_View_Update(void)
5406 {
5407         R_Main_ResizeViewCache();
5408         R_View_SetFrustum(NULL);
5409         R_View_WorldVisibility(r_refdef.view.useclipplane);
5410         R_View_UpdateEntityVisible();
5411         R_View_UpdateEntityLighting();
5412 }
5413
5414 float viewscalefpsadjusted = 1.0f;
5415
5416 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5417 {
5418         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5419         scale = bound(0.03125f, scale, 1.0f);
5420         *outwidth = (int)ceil(width * scale);
5421         *outheight = (int)ceil(height * scale);
5422 }
5423
5424 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5425 {
5426         const float *customclipplane = NULL;
5427         float plane[4];
5428         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5429         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5430         {
5431                 // LordHavoc: couldn't figure out how to make this approach the
5432                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5433                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5434                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5435                         dist = r_refdef.view.clipplane.dist;
5436                 plane[0] = r_refdef.view.clipplane.normal[0];
5437                 plane[1] = r_refdef.view.clipplane.normal[1];
5438                 plane[2] = r_refdef.view.clipplane.normal[2];
5439                 plane[3] = -dist;
5440                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5441         }
5442
5443         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5444         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5445
5446         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5447         if (!r_refdef.view.useperspective)
5448                 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);
5449         else if (vid.stencil && r_useinfinitefarclip.integer)
5450                 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);
5451         else
5452                 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);
5453         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5454         R_SetViewport(&r_refdef.view.viewport);
5455         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5456         {
5457                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5458                 float screenplane[4];
5459                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5460                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5461                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5462                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5463                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5464         }
5465 }
5466
5467 void R_EntityMatrix(const matrix4x4_t *matrix)
5468 {
5469         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5470         {
5471                 gl_modelmatrixchanged = false;
5472                 gl_modelmatrix = *matrix;
5473                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5474                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5475                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5476                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5477                 CHECKGLERROR
5478                 switch(vid.renderpath)
5479                 {
5480                 case RENDERPATH_D3D9:
5481 #ifdef SUPPORTD3D
5482                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5483                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5484 #endif
5485                         break;
5486                 case RENDERPATH_D3D10:
5487                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5488                         break;
5489                 case RENDERPATH_D3D11:
5490                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5491                         break;
5492                 case RENDERPATH_GL11:
5493                 case RENDERPATH_GL13:
5494                 case RENDERPATH_GLES1:
5495                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5496                         break;
5497                 case RENDERPATH_SOFT:
5498                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5499                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5500                         break;
5501                 case RENDERPATH_GL20:
5502                 case RENDERPATH_GLES2:
5503                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5504                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5505                         break;
5506                 }
5507         }
5508 }
5509
5510 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5511 {
5512         r_viewport_t viewport;
5513
5514         CHECKGLERROR
5515
5516         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5517         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);
5518         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5519         R_SetViewport(&viewport);
5520         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5521         GL_Color(1, 1, 1, 1);
5522         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5523         GL_BlendFunc(GL_ONE, GL_ZERO);
5524         GL_ScissorTest(false);
5525         GL_DepthMask(false);
5526         GL_DepthRange(0, 1);
5527         GL_DepthTest(false);
5528         GL_DepthFunc(GL_LEQUAL);
5529         R_EntityMatrix(&identitymatrix);
5530         R_Mesh_ResetTextureState();
5531         GL_PolygonOffset(0, 0);
5532         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5533         switch(vid.renderpath)
5534         {
5535         case RENDERPATH_GL11:
5536         case RENDERPATH_GL13:
5537         case RENDERPATH_GL20:
5538         case RENDERPATH_GLES1:
5539         case RENDERPATH_GLES2:
5540                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5541                 break;
5542         case RENDERPATH_D3D9:
5543         case RENDERPATH_D3D10:
5544         case RENDERPATH_D3D11:
5545         case RENDERPATH_SOFT:
5546                 break;
5547         }
5548         GL_CullFace(GL_NONE);
5549
5550         CHECKGLERROR
5551 }
5552
5553 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5554 {
5555         DrawQ_Finish();
5556
5557         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5558 }
5559
5560 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5561 {
5562         DrawQ_Finish();
5563
5564         R_SetupView(true, fbo, depthtexture, colortexture);
5565         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5566         GL_Color(1, 1, 1, 1);
5567         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5568         GL_BlendFunc(GL_ONE, GL_ZERO);
5569         GL_ScissorTest(true);
5570         GL_DepthMask(true);
5571         GL_DepthRange(0, 1);
5572         GL_DepthTest(true);
5573         GL_DepthFunc(GL_LEQUAL);
5574         R_EntityMatrix(&identitymatrix);
5575         R_Mesh_ResetTextureState();
5576         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5577         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5578         switch(vid.renderpath)
5579         {
5580         case RENDERPATH_GL11:
5581         case RENDERPATH_GL13:
5582         case RENDERPATH_GL20:
5583         case RENDERPATH_GLES1:
5584         case RENDERPATH_GLES2:
5585                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5586                 break;
5587         case RENDERPATH_D3D9:
5588         case RENDERPATH_D3D10:
5589         case RENDERPATH_D3D11:
5590         case RENDERPATH_SOFT:
5591                 break;
5592         }
5593         GL_CullFace(r_refdef.view.cullface_back);
5594 }
5595
5596 /*
5597 ================
5598 R_RenderView_UpdateViewVectors
5599 ================
5600 */
5601 void R_RenderView_UpdateViewVectors(void)
5602 {
5603         // break apart the view matrix into vectors for various purposes
5604         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5605         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5606         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5607         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5608         // make an inverted copy of the view matrix for tracking sprites
5609         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5610 }
5611
5612 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5613 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5614
5615 static void R_Water_StartFrame(void)
5616 {
5617         int i;
5618         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5619         r_waterstate_waterplane_t *p;
5620         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;
5621
5622         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5623                 return;
5624
5625         switch(vid.renderpath)
5626         {
5627         case RENDERPATH_GL20:
5628         case RENDERPATH_D3D9:
5629         case RENDERPATH_D3D10:
5630         case RENDERPATH_D3D11:
5631         case RENDERPATH_SOFT:
5632         case RENDERPATH_GLES2:
5633                 break;
5634         case RENDERPATH_GL11:
5635         case RENDERPATH_GL13:
5636         case RENDERPATH_GLES1:
5637                 return;
5638         }
5639
5640         // set waterwidth and waterheight to the water resolution that will be
5641         // used (often less than the screen resolution for faster rendering)
5642         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5643
5644         // calculate desired texture sizes
5645         // can't use water if the card does not support the texture size
5646         if (!r_water.integer || r_showsurfaces.integer)
5647                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5648         else if (vid.support.arb_texture_non_power_of_two)
5649         {
5650                 texturewidth = waterwidth;
5651                 textureheight = waterheight;
5652                 camerawidth = waterwidth;
5653                 cameraheight = waterheight;
5654         }
5655         else
5656         {
5657                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5658                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5659                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5660                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5661         }
5662
5663         // allocate textures as needed
5664         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))
5665         {
5666                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5667                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5668                 {
5669                         if (p->texture_refraction)
5670                                 R_FreeTexture(p->texture_refraction);
5671                         p->texture_refraction = NULL;
5672                         if (p->fbo_refraction)
5673                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5674                         p->fbo_refraction = 0;
5675                         if (p->texture_reflection)
5676                                 R_FreeTexture(p->texture_reflection);
5677                         p->texture_reflection = NULL;
5678                         if (p->fbo_reflection)
5679                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5680                         p->fbo_reflection = 0;
5681                         if (p->texture_camera)
5682                                 R_FreeTexture(p->texture_camera);
5683                         p->texture_camera = NULL;
5684                         if (p->fbo_camera)
5685                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5686                         p->fbo_camera = 0;
5687                 }
5688                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5689                 r_fb.water.texturewidth = texturewidth;
5690                 r_fb.water.textureheight = textureheight;
5691                 r_fb.water.camerawidth = camerawidth;
5692                 r_fb.water.cameraheight = cameraheight;
5693         }
5694
5695         if (r_fb.water.texturewidth)
5696         {
5697                 int scaledwidth, scaledheight;
5698
5699                 r_fb.water.enabled = true;
5700
5701                 // water resolution is usually reduced
5702                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5703                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5704                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5705
5706                 // set up variables that will be used in shader setup
5707                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5708                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5709                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5710                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5711         }
5712
5713         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5714         r_fb.water.numwaterplanes = 0;
5715 }
5716
5717 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5718 {
5719         int planeindex, bestplaneindex, vertexindex;
5720         vec3_t mins, maxs, normal, center, v, n;
5721         vec_t planescore, bestplanescore;
5722         mplane_t plane;
5723         r_waterstate_waterplane_t *p;
5724         texture_t *t = R_GetCurrentTexture(surface->texture);
5725
5726         rsurface.texture = t;
5727         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5728         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5729         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5730                 return;
5731         // average the vertex normals, find the surface bounds (after deformvertexes)
5732         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5733         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5734         VectorCopy(n, normal);
5735         VectorCopy(v, mins);
5736         VectorCopy(v, maxs);
5737         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5738         {
5739                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5740                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5741                 VectorAdd(normal, n, normal);
5742                 mins[0] = min(mins[0], v[0]);
5743                 mins[1] = min(mins[1], v[1]);
5744                 mins[2] = min(mins[2], v[2]);
5745                 maxs[0] = max(maxs[0], v[0]);
5746                 maxs[1] = max(maxs[1], v[1]);
5747                 maxs[2] = max(maxs[2], v[2]);
5748         }
5749         VectorNormalize(normal);
5750         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5751
5752         VectorCopy(normal, plane.normal);
5753         VectorNormalize(plane.normal);
5754         plane.dist = DotProduct(center, plane.normal);
5755         PlaneClassify(&plane);
5756         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5757         {
5758                 // skip backfaces (except if nocullface is set)
5759 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5760 //                      return;
5761                 VectorNegate(plane.normal, plane.normal);
5762                 plane.dist *= -1;
5763                 PlaneClassify(&plane);
5764         }
5765
5766
5767         // find a matching plane if there is one
5768         bestplaneindex = -1;
5769         bestplanescore = 1048576.0f;
5770         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5771         {
5772                 if(p->camera_entity == t->camera_entity)
5773                 {
5774                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5775                         if (bestplaneindex < 0 || bestplanescore > planescore)
5776                         {
5777                                 bestplaneindex = planeindex;
5778                                 bestplanescore = planescore;
5779                         }
5780                 }
5781         }
5782         planeindex = bestplaneindex;
5783         p = r_fb.water.waterplanes + planeindex;
5784
5785         // if this surface does not fit any known plane rendered this frame, add one
5786         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5787         {
5788                 // store the new plane
5789                 planeindex = r_fb.water.numwaterplanes++;
5790                 p = r_fb.water.waterplanes + planeindex;
5791                 p->plane = plane;
5792                 // clear materialflags and pvs
5793                 p->materialflags = 0;
5794                 p->pvsvalid = false;
5795                 p->camera_entity = t->camera_entity;
5796                 VectorCopy(mins, p->mins);
5797                 VectorCopy(maxs, p->maxs);
5798         }
5799         else
5800         {
5801                 // merge mins/maxs when we're adding this surface to the plane
5802                 p->mins[0] = min(p->mins[0], mins[0]);
5803                 p->mins[1] = min(p->mins[1], mins[1]);
5804                 p->mins[2] = min(p->mins[2], mins[2]);
5805                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5806                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5807                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5808         }
5809         // merge this surface's materialflags into the waterplane
5810         p->materialflags |= t->currentmaterialflags;
5811         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5812         {
5813                 // merge this surface's PVS into the waterplane
5814                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5815                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5816                 {
5817                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5818                         p->pvsvalid = true;
5819                 }
5820         }
5821 }
5822
5823 extern cvar_t r_drawparticles;
5824 extern cvar_t r_drawdecals;
5825
5826 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5827 {
5828         int myscissor[4];
5829         r_refdef_view_t originalview;
5830         r_refdef_view_t myview;
5831         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;
5832         r_waterstate_waterplane_t *p;
5833         vec3_t visorigin;
5834         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;
5835         char vabuf[1024];
5836
5837         originalview = r_refdef.view;
5838
5839         // lowquality hack, temporarily shut down some cvars and restore afterwards
5840         qualityreduction = r_water_lowquality.integer;
5841         if (qualityreduction > 0)
5842         {
5843                 if (qualityreduction >= 1)
5844                 {
5845                         old_r_shadows = r_shadows.integer;
5846                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5847                         old_r_dlight = r_shadow_realtime_dlight.integer;
5848                         Cvar_SetValueQuick(&r_shadows, 0);
5849                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5850                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5851                 }
5852                 if (qualityreduction >= 2)
5853                 {
5854                         old_r_dynamic = r_dynamic.integer;
5855                         old_r_particles = r_drawparticles.integer;
5856                         old_r_decals = r_drawdecals.integer;
5857                         Cvar_SetValueQuick(&r_dynamic, 0);
5858                         Cvar_SetValueQuick(&r_drawparticles, 0);
5859                         Cvar_SetValueQuick(&r_drawdecals, 0);
5860                 }
5861         }
5862
5863         // make sure enough textures are allocated
5864         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5865         {
5866                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5867                 {
5868                         if (!p->texture_refraction)
5869                                 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);
5870                         if (!p->texture_refraction)
5871                                 goto error;
5872                         if (usewaterfbo)
5873                         {
5874                                 if (r_fb.water.depthtexture == NULL)
5875                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5876                                 if (p->fbo_refraction == 0)
5877                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5878                         }
5879                 }
5880                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5881                 {
5882                         if (!p->texture_camera)
5883                                 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);
5884                         if (!p->texture_camera)
5885                                 goto error;
5886                         if (usewaterfbo)
5887                         {
5888                                 if (r_fb.water.depthtexture == NULL)
5889                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5890                                 if (p->fbo_camera == 0)
5891                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5892                         }
5893                 }
5894
5895                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5896                 {
5897                         if (!p->texture_reflection)
5898                                 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);
5899                         if (!p->texture_reflection)
5900                                 goto error;
5901                         if (usewaterfbo)
5902                         {
5903                                 if (r_fb.water.depthtexture == NULL)
5904                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5905                                 if (p->fbo_reflection == 0)
5906                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5907                         }
5908                 }
5909         }
5910
5911         // render views
5912         r_refdef.view = originalview;
5913         r_refdef.view.showdebug = false;
5914         r_refdef.view.width = r_fb.water.waterwidth;
5915         r_refdef.view.height = r_fb.water.waterheight;
5916         r_refdef.view.useclipplane = true;
5917         myview = r_refdef.view;
5918         r_fb.water.renderingscene = true;
5919         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5920         {
5921                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5922                 {
5923                         r_refdef.view = myview;
5924                         if(r_water_scissormode.integer)
5925                         {
5926                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5927                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5928                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5929                         }
5930
5931                         // render reflected scene and copy into texture
5932                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5933                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5934                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5935                         r_refdef.view.clipplane = p->plane;
5936                         // reverse the cullface settings for this render
5937                         r_refdef.view.cullface_front = GL_FRONT;
5938                         r_refdef.view.cullface_back = GL_BACK;
5939                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5940                         {
5941                                 r_refdef.view.usecustompvs = true;
5942                                 if (p->pvsvalid)
5943                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5944                                 else
5945                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5946                         }
5947
5948                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5949                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5950                         R_ClearScreen(r_refdef.fogenabled);
5951                         if(r_water_scissormode.integer & 2)
5952                                 R_View_UpdateWithScissor(myscissor);
5953                         else
5954                                 R_View_Update();
5955                         R_AnimCache_CacheVisibleEntities();
5956                         if(r_water_scissormode.integer & 1)
5957                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5958                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5959
5960                         if (!p->fbo_reflection)
5961                                 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);
5962                         r_fb.water.hideplayer = false;
5963                 }
5964
5965                 // render the normal view scene and copy into texture
5966                 // (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)
5967                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5968                 {
5969                         r_refdef.view = myview;
5970                         if(r_water_scissormode.integer)
5971                         {
5972                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5973                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5974                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5975                         }
5976
5977                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5978
5979                         r_refdef.view.clipplane = p->plane;
5980                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5981                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5982
5983                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5984                         {
5985                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5986                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5987                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5988                                 R_RenderView_UpdateViewVectors();
5989                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5990                                 {
5991                                         r_refdef.view.usecustompvs = true;
5992                                         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);
5993                                 }
5994                         }
5995
5996                         PlaneClassify(&r_refdef.view.clipplane);
5997
5998                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5999                         R_ClearScreen(r_refdef.fogenabled);
6000                         if(r_water_scissormode.integer & 2)
6001                                 R_View_UpdateWithScissor(myscissor);
6002                         else
6003                                 R_View_Update();
6004                         R_AnimCache_CacheVisibleEntities();
6005                         if(r_water_scissormode.integer & 1)
6006                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6007                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6008
6009                         if (!p->fbo_refraction)
6010                                 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);
6011                         r_fb.water.hideplayer = false;
6012                 }
6013                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6014                 {
6015                         r_refdef.view = myview;
6016
6017                         r_refdef.view.clipplane = p->plane;
6018                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6019                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6020
6021                         r_refdef.view.width = r_fb.water.camerawidth;
6022                         r_refdef.view.height = r_fb.water.cameraheight;
6023                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6024                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6025                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6026                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6027
6028                         if(p->camera_entity)
6029                         {
6030                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6031                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6032                         }
6033
6034                         // note: all of the view is used for displaying... so
6035                         // there is no use in scissoring
6036
6037                         // reverse the cullface settings for this render
6038                         r_refdef.view.cullface_front = GL_FRONT;
6039                         r_refdef.view.cullface_back = GL_BACK;
6040                         // also reverse the view matrix
6041                         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
6042                         R_RenderView_UpdateViewVectors();
6043                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6044                         {
6045                                 r_refdef.view.usecustompvs = true;
6046                                 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);
6047                         }
6048                         
6049                         // camera needs no clipplane
6050                         r_refdef.view.useclipplane = false;
6051
6052                         PlaneClassify(&r_refdef.view.clipplane);
6053
6054                         r_fb.water.hideplayer = false;
6055
6056                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6057                         R_ClearScreen(r_refdef.fogenabled);
6058                         R_View_Update();
6059                         R_AnimCache_CacheVisibleEntities();
6060                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6061
6062                         if (!p->fbo_camera)
6063                                 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);
6064                         r_fb.water.hideplayer = false;
6065                 }
6066
6067         }
6068         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6069         r_fb.water.renderingscene = false;
6070         r_refdef.view = originalview;
6071         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6072         if (!r_fb.water.depthtexture)
6073                 R_ClearScreen(r_refdef.fogenabled);
6074         R_View_Update();
6075         R_AnimCache_CacheVisibleEntities();
6076         goto finish;
6077 error:
6078         r_refdef.view = originalview;
6079         r_fb.water.renderingscene = false;
6080         Cvar_SetValueQuick(&r_water, 0);
6081         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6082 finish:
6083         // lowquality hack, restore cvars
6084         if (qualityreduction > 0)
6085         {
6086                 if (qualityreduction >= 1)
6087                 {
6088                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6089                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6090                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6091                 }
6092                 if (qualityreduction >= 2)
6093                 {
6094                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6095                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6096                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6097                 }
6098         }
6099 }
6100
6101 static void R_Bloom_StartFrame(void)
6102 {
6103         int i;
6104         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6105         int viewwidth, viewheight;
6106         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6107         textype_t textype = TEXTYPE_COLORBUFFER;
6108
6109         switch (vid.renderpath)
6110         {
6111         case RENDERPATH_GL20:
6112                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6113                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6114                 {
6115                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6116                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6117                 }
6118                 break;
6119         case RENDERPATH_GL11:
6120         case RENDERPATH_GL13:
6121         case RENDERPATH_GLES1:
6122         case RENDERPATH_GLES2:
6123         case RENDERPATH_D3D9:
6124         case RENDERPATH_D3D10:
6125         case RENDERPATH_D3D11:
6126                 r_fb.usedepthtextures = false;
6127                 break;
6128         case RENDERPATH_SOFT:
6129                 r_fb.usedepthtextures = true;
6130                 break;
6131         }
6132
6133         if (r_viewscale_fpsscaling.integer)
6134         {
6135                 double actualframetime;
6136                 double targetframetime;
6137                 double adjust;
6138                 actualframetime = r_refdef.lastdrawscreentime;
6139                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6140                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6141                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6142                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6143                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6144                 viewscalefpsadjusted += adjust;
6145                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6146         }
6147         else
6148                 viewscalefpsadjusted = 1.0f;
6149
6150         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6151
6152         switch(vid.renderpath)
6153         {
6154         case RENDERPATH_GL20:
6155         case RENDERPATH_D3D9:
6156         case RENDERPATH_D3D10:
6157         case RENDERPATH_D3D11:
6158         case RENDERPATH_SOFT:
6159         case RENDERPATH_GLES2:
6160                 break;
6161         case RENDERPATH_GL11:
6162         case RENDERPATH_GL13:
6163         case RENDERPATH_GLES1:
6164                 return;
6165         }
6166
6167         // set bloomwidth and bloomheight to the bloom resolution that will be
6168         // used (often less than the screen resolution for faster rendering)
6169         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6170         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6171         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6172         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6173         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6174
6175         // calculate desired texture sizes
6176         if (vid.support.arb_texture_non_power_of_two)
6177         {
6178                 screentexturewidth = vid.width;
6179                 screentextureheight = vid.height;
6180                 bloomtexturewidth = r_fb.bloomwidth;
6181                 bloomtextureheight = r_fb.bloomheight;
6182         }
6183         else
6184         {
6185                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6186                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6187                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6188                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6189         }
6190
6191         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))
6192         {
6193                 Cvar_SetValueQuick(&r_bloom, 0);
6194                 Cvar_SetValueQuick(&r_motionblur, 0);
6195                 Cvar_SetValueQuick(&r_damageblur, 0);
6196         }
6197
6198         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6199          && !r_bloom.integer
6200          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6201          && !useviewfbo
6202          && r_viewscale.value == 1.0f
6203          && !r_viewscale_fpsscaling.integer)
6204                 screentexturewidth = screentextureheight = 0;
6205         if (!r_bloom.integer)
6206                 bloomtexturewidth = bloomtextureheight = 0;
6207
6208         // allocate textures as needed
6209         if (r_fb.screentexturewidth != screentexturewidth
6210          || r_fb.screentextureheight != screentextureheight
6211          || r_fb.bloomtexturewidth != bloomtexturewidth
6212          || r_fb.bloomtextureheight != bloomtextureheight
6213          || r_fb.textype != textype
6214          || useviewfbo != (r_fb.fbo != 0))
6215         {
6216                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6217                 {
6218                         if (r_fb.bloomtexture[i])
6219                                 R_FreeTexture(r_fb.bloomtexture[i]);
6220                         r_fb.bloomtexture[i] = NULL;
6221
6222                         if (r_fb.bloomfbo[i])
6223                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6224                         r_fb.bloomfbo[i] = 0;
6225                 }
6226
6227                 if (r_fb.fbo)
6228                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6229                 r_fb.fbo = 0;
6230
6231                 if (r_fb.colortexture)
6232                         R_FreeTexture(r_fb.colortexture);
6233                 r_fb.colortexture = NULL;
6234
6235                 if (r_fb.depthtexture)
6236                         R_FreeTexture(r_fb.depthtexture);
6237                 r_fb.depthtexture = NULL;
6238
6239                 if (r_fb.ghosttexture)
6240                         R_FreeTexture(r_fb.ghosttexture);
6241                 r_fb.ghosttexture = NULL;
6242
6243                 r_fb.screentexturewidth = screentexturewidth;
6244                 r_fb.screentextureheight = screentextureheight;
6245                 r_fb.bloomtexturewidth = bloomtexturewidth;
6246                 r_fb.bloomtextureheight = bloomtextureheight;
6247                 r_fb.textype = textype;
6248
6249                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6250                 {
6251                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6252                                 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);
6253                         r_fb.ghosttexture_valid = false;
6254                         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);
6255                         if (useviewfbo)
6256                         {
6257                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6258                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6259                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6260                         }
6261                 }
6262
6263                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6264                 {
6265                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6266                         {
6267                                 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);
6268                                 if (useviewfbo)
6269                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6270                         }
6271                 }
6272         }
6273
6274         // bloom texture is a different resolution
6275         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6276         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6277         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6278         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6279         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6280
6281         // set up a texcoord array for the full resolution screen image
6282         // (we have to keep this around to copy back during final render)
6283         r_fb.screentexcoord2f[0] = 0;
6284         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6285         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6286         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6287         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6288         r_fb.screentexcoord2f[5] = 0;
6289         r_fb.screentexcoord2f[6] = 0;
6290         r_fb.screentexcoord2f[7] = 0;
6291
6292         if(r_fb.fbo) 
6293         {
6294                 for (i = 1;i < 8;i += 2)
6295                 {
6296                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6297                 }
6298         }
6299
6300         // set up a texcoord array for the reduced resolution bloom image
6301         // (which will be additive blended over the screen image)
6302         r_fb.bloomtexcoord2f[0] = 0;
6303         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6304         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6305         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6306         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6307         r_fb.bloomtexcoord2f[5] = 0;
6308         r_fb.bloomtexcoord2f[6] = 0;
6309         r_fb.bloomtexcoord2f[7] = 0;
6310
6311         switch(vid.renderpath)
6312         {
6313         case RENDERPATH_GL11:
6314         case RENDERPATH_GL13:
6315         case RENDERPATH_GL20:
6316         case RENDERPATH_SOFT:
6317         case RENDERPATH_GLES1:
6318         case RENDERPATH_GLES2:
6319                 break;
6320         case RENDERPATH_D3D9:
6321         case RENDERPATH_D3D10:
6322         case RENDERPATH_D3D11:
6323                 for (i = 0;i < 4;i++)
6324                 {
6325                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6326                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6327                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6328                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6329                 }
6330                 break;
6331         }
6332
6333         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6334
6335         if (r_fb.fbo)
6336                 r_refdef.view.clear = true;
6337 }
6338
6339 static void R_Bloom_MakeTexture(void)
6340 {
6341         int x, range, dir;
6342         float xoffset, yoffset, r, brighten;
6343         rtexture_t *intex;
6344         float colorscale = r_bloom_colorscale.value;
6345
6346         r_refdef.stats.bloom++;
6347     
6348 #if 0
6349     // this copy is unnecessary since it happens in R_BlendView already
6350         if (!r_fb.fbo)
6351         {
6352                 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);
6353                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6354         }
6355 #endif
6356
6357         // scale down screen texture to the bloom texture size
6358         CHECKGLERROR
6359         r_fb.bloomindex = 0;
6360         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6361         R_SetViewport(&r_fb.bloomviewport);
6362         GL_DepthTest(false);
6363         GL_BlendFunc(GL_ONE, GL_ZERO);
6364         GL_Color(colorscale, colorscale, colorscale, 1);
6365         // 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...
6366         switch(vid.renderpath)
6367         {
6368         case RENDERPATH_GL11:
6369         case RENDERPATH_GL13:
6370         case RENDERPATH_GL20:
6371         case RENDERPATH_GLES1:
6372         case RENDERPATH_GLES2:
6373         case RENDERPATH_SOFT:
6374                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6375                 break;
6376         case RENDERPATH_D3D9:
6377         case RENDERPATH_D3D10:
6378         case RENDERPATH_D3D11:
6379                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6380                 break;
6381         }
6382         // TODO: do boxfilter scale-down in shader?
6383         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6384         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6385         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6386
6387         // we now have a properly scaled bloom image
6388         if (!r_fb.bloomfbo[r_fb.bloomindex])
6389         {
6390                 // copy it into the bloom texture
6391                 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);
6392                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6393         }
6394
6395         // multiply bloom image by itself as many times as desired
6396         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6397         {
6398                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6399                 r_fb.bloomindex ^= 1;
6400                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6401                 x *= 2;
6402                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6403                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6404                 {
6405                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6406                         GL_Color(r,r,r,1); // apply fix factor
6407                 }
6408                 else
6409                 {
6410                         if(x <= 2)
6411                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6412                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6413                         GL_Color(1,1,1,1); // no fix factor supported here
6414                 }
6415                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6416                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6417                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6418                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6419
6420                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6421                 {
6422                         // copy the darkened image to a texture
6423                         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);
6424                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6425                 }
6426         }
6427
6428         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6429         brighten = r_bloom_brighten.value;
6430         brighten = sqrt(brighten);
6431         if(range >= 1)
6432                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6433
6434         for (dir = 0;dir < 2;dir++)
6435         {
6436                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6437                 r_fb.bloomindex ^= 1;
6438                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6439                 // blend on at multiple vertical offsets to achieve a vertical blur
6440                 // TODO: do offset blends using GLSL
6441                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6442                 GL_BlendFunc(GL_ONE, GL_ZERO);
6443                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6444                 for (x = -range;x <= range;x++)
6445                 {
6446                         if (!dir){xoffset = 0;yoffset = x;}
6447                         else {xoffset = x;yoffset = 0;}
6448                         xoffset /= (float)r_fb.bloomtexturewidth;
6449                         yoffset /= (float)r_fb.bloomtextureheight;
6450                         // compute a texcoord array with the specified x and y offset
6451                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6452                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6453                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6454                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6455                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6456                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6457                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6458                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6459                         // this r value looks like a 'dot' particle, fading sharply to
6460                         // black at the edges
6461                         // (probably not realistic but looks good enough)
6462                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6463                         //r = brighten/(range*2+1);
6464                         r = brighten / (range * 2 + 1);
6465                         if(range >= 1)
6466                                 r *= (1 - x*x/(float)(range*range));
6467                         GL_Color(r, r, r, 1);
6468                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6469                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6470                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6471                         GL_BlendFunc(GL_ONE, GL_ONE);
6472                 }
6473
6474                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6475                 {
6476                         // copy the vertically or horizontally blurred bloom view to a texture
6477                         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);
6478                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6479                 }
6480         }
6481 }
6482
6483 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6484 {
6485         unsigned int permutation;
6486         float uservecs[4][4];
6487
6488         R_EntityMatrix(&identitymatrix);
6489
6490         switch (vid.renderpath)
6491         {
6492         case RENDERPATH_GL20:
6493         case RENDERPATH_D3D9:
6494         case RENDERPATH_D3D10:
6495         case RENDERPATH_D3D11:
6496         case RENDERPATH_SOFT:
6497         case RENDERPATH_GLES2:
6498                 permutation =
6499                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6500                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6501                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6502                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6503                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6504
6505                 if (r_fb.colortexture)
6506                 {
6507                         if (!r_fb.fbo)
6508                         {
6509                                 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);
6510                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6511                         }
6512
6513                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6514                         {
6515                                 // declare variables
6516                                 float blur_factor, blur_mouseaccel, blur_velocity;
6517                                 static float blur_average; 
6518                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6519
6520                                 // set a goal for the factoring
6521                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6522                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6523                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6524                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6525                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6526                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6527
6528                                 // from the goal, pick an averaged value between goal and last value
6529                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6530                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6531
6532                                 // enforce minimum amount of blur 
6533                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6534
6535                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6536
6537                                 // calculate values into a standard alpha
6538                                 cl.motionbluralpha = 1 - exp(-
6539                                                 (
6540                                                  (r_motionblur.value * blur_factor / 80)
6541                                                  +
6542                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6543                                                 )
6544                                                 /
6545                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6546                                           );
6547
6548                                 // randomization for the blur value to combat persistent ghosting
6549                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6550                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6551
6552                                 // apply the blur
6553                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6554                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6555                                 {
6556                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6557                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6558                                         switch(vid.renderpath)
6559                                         {
6560                                         case RENDERPATH_GL11:
6561                                         case RENDERPATH_GL13:
6562                                         case RENDERPATH_GL20:
6563                                         case RENDERPATH_GLES1:
6564                                         case RENDERPATH_GLES2:
6565                                         case RENDERPATH_SOFT:
6566                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6567                                                 break;
6568                                         case RENDERPATH_D3D9:
6569                                         case RENDERPATH_D3D10:
6570                                         case RENDERPATH_D3D11:
6571                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6572                                                 break;
6573                                         }
6574                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6575                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6576                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6577                                 }
6578
6579                                 // updates old view angles for next pass
6580                                 VectorCopy(cl.viewangles, blur_oldangles);
6581
6582                                 // copy view into the ghost texture
6583                                 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);
6584                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6585                                 r_fb.ghosttexture_valid = true;
6586                         }
6587                 }
6588                 else
6589                 {
6590                         // no r_fb.colortexture means we're rendering to the real fb
6591                         // we may still have to do view tint...
6592                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6593                         {
6594                                 // apply a color tint to the whole view
6595                                 R_ResetViewRendering2D(0, NULL, NULL);
6596                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6597                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6598                                 R_SetupShader_Generic_NoTexture(false, true);
6599                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6600                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6601                         }
6602                         break; // no screen processing, no bloom, skip it
6603                 }
6604
6605                 if (r_fb.bloomtexture[0])
6606                 {
6607                         // make the bloom texture
6608                         R_Bloom_MakeTexture();
6609                 }
6610
6611 #if _MSC_VER >= 1400
6612 #define sscanf sscanf_s
6613 #endif
6614                 memset(uservecs, 0, sizeof(uservecs));
6615                 if (r_glsl_postprocess_uservec1_enable.integer)
6616                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6617                 if (r_glsl_postprocess_uservec2_enable.integer)
6618                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6619                 if (r_glsl_postprocess_uservec3_enable.integer)
6620                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6621                 if (r_glsl_postprocess_uservec4_enable.integer)
6622                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6623
6624                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6625                 GL_Color(1, 1, 1, 1);
6626                 GL_BlendFunc(GL_ONE, GL_ZERO);
6627
6628                 switch(vid.renderpath)
6629                 {
6630                 case RENDERPATH_GL20:
6631                 case RENDERPATH_GLES2:
6632                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6633                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6634                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6635                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6636                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6637                         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]);
6638                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6639                         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]);
6640                         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]);
6641                         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]);
6642                         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]);
6643                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6644                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6645                         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);
6646                         break;
6647                 case RENDERPATH_D3D9:
6648 #ifdef SUPPORTD3D
6649                         // 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...
6650                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6651                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6652                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6653                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6654                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6655                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6656                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6657                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6658                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6659                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6660                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6661                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6662                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6663                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6664 #endif
6665                         break;
6666                 case RENDERPATH_D3D10:
6667                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6668                         break;
6669                 case RENDERPATH_D3D11:
6670                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6671                         break;
6672                 case RENDERPATH_SOFT:
6673                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6674                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6675                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6676                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6677                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6678                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6679                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6680                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6681                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6682                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6683                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6684                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6685                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6686                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6687                         break;
6688                 default:
6689                         break;
6690                 }
6691                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6692                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6693                 break;
6694         case RENDERPATH_GL11:
6695         case RENDERPATH_GL13:
6696         case RENDERPATH_GLES1:
6697                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6698                 {
6699                         // apply a color tint to the whole view
6700                         R_ResetViewRendering2D(0, NULL, NULL);
6701                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6702                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6703                         R_SetupShader_Generic_NoTexture(false, true);
6704                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6705                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6706                 }
6707                 break;
6708         }
6709 }
6710
6711 matrix4x4_t r_waterscrollmatrix;
6712
6713 void R_UpdateFog(void)
6714 {
6715         // Nehahra fog
6716         if (gamemode == GAME_NEHAHRA)
6717         {
6718                 if (gl_fogenable.integer)
6719                 {
6720                         r_refdef.oldgl_fogenable = true;
6721                         r_refdef.fog_density = gl_fogdensity.value;
6722                         r_refdef.fog_red = gl_fogred.value;
6723                         r_refdef.fog_green = gl_foggreen.value;
6724                         r_refdef.fog_blue = gl_fogblue.value;
6725                         r_refdef.fog_alpha = 1;
6726                         r_refdef.fog_start = 0;
6727                         r_refdef.fog_end = gl_skyclip.value;
6728                         r_refdef.fog_height = 1<<30;
6729                         r_refdef.fog_fadedepth = 128;
6730                 }
6731                 else if (r_refdef.oldgl_fogenable)
6732                 {
6733                         r_refdef.oldgl_fogenable = false;
6734                         r_refdef.fog_density = 0;
6735                         r_refdef.fog_red = 0;
6736                         r_refdef.fog_green = 0;
6737                         r_refdef.fog_blue = 0;
6738                         r_refdef.fog_alpha = 0;
6739                         r_refdef.fog_start = 0;
6740                         r_refdef.fog_end = 0;
6741                         r_refdef.fog_height = 1<<30;
6742                         r_refdef.fog_fadedepth = 128;
6743                 }
6744         }
6745
6746         // fog parms
6747         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6748         r_refdef.fog_start = max(0, r_refdef.fog_start);
6749         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6750
6751         if (r_refdef.fog_density && r_drawfog.integer)
6752         {
6753                 r_refdef.fogenabled = true;
6754                 // this is the point where the fog reaches 0.9986 alpha, which we
6755                 // consider a good enough cutoff point for the texture
6756                 // (0.9986 * 256 == 255.6)
6757                 if (r_fog_exp2.integer)
6758                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6759                 else
6760                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6761                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6762                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6763                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6764                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6765                         R_BuildFogHeightTexture();
6766                 // fog color was already set
6767                 // update the fog texture
6768                 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)
6769                         R_BuildFogTexture();
6770                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6771                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6772         }
6773         else
6774                 r_refdef.fogenabled = false;
6775
6776         // fog color
6777         if (r_refdef.fog_density)
6778         {
6779                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6780                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6781                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6782
6783                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6784                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6785                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6786                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6787
6788                 {
6789                         vec3_t fogvec;
6790                         VectorCopy(r_refdef.fogcolor, fogvec);
6791                         //   color.rgb *= ContrastBoost * SceneBrightness;
6792                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6793                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6794                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6795                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6796                 }
6797         }
6798 }
6799
6800 void R_UpdateVariables(void)
6801 {
6802         R_Textures_Frame();
6803
6804         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6805
6806         r_refdef.farclip = r_farclip_base.value;
6807         if (r_refdef.scene.worldmodel)
6808                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6809         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6810
6811         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6812                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6813         r_refdef.polygonfactor = 0;
6814         r_refdef.polygonoffset = 0;
6815         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6816         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6817
6818         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6819         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6820         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6821         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6822         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6823         if (FAKELIGHT_ENABLED)
6824         {
6825                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6826         }
6827         else if (r_refdef.scene.worldmodel)
6828         {
6829                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6830         }
6831         if (r_showsurfaces.integer)
6832         {
6833                 r_refdef.scene.rtworld = false;
6834                 r_refdef.scene.rtworldshadows = false;
6835                 r_refdef.scene.rtdlight = false;
6836                 r_refdef.scene.rtdlightshadows = false;
6837                 r_refdef.lightmapintensity = 0;
6838         }
6839
6840         switch(vid.renderpath)
6841         {
6842         case RENDERPATH_GL20:
6843         case RENDERPATH_D3D9:
6844         case RENDERPATH_D3D10:
6845         case RENDERPATH_D3D11:
6846         case RENDERPATH_SOFT:
6847         case RENDERPATH_GLES2:
6848                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6849                 {
6850                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6851                         {
6852                                 // build GLSL gamma texture
6853 #define RAMPWIDTH 256
6854                                 unsigned short ramp[RAMPWIDTH * 3];
6855                                 unsigned char rampbgr[RAMPWIDTH][4];
6856                                 int i;
6857
6858                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6859
6860                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6861                                 for(i = 0; i < RAMPWIDTH; ++i)
6862                                 {
6863                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6864                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6865                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6866                                         rampbgr[i][3] = 0;
6867                                 }
6868                                 if (r_texture_gammaramps)
6869                                 {
6870                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6871                                 }
6872                                 else
6873                                 {
6874                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6875                                 }
6876                         }
6877                 }
6878                 else
6879                 {
6880                         // remove GLSL gamma texture
6881                 }
6882                 break;
6883         case RENDERPATH_GL11:
6884         case RENDERPATH_GL13:
6885         case RENDERPATH_GLES1:
6886                 break;
6887         }
6888 }
6889
6890 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6891 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6892 /*
6893 ================
6894 R_SelectScene
6895 ================
6896 */
6897 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6898         if( scenetype != r_currentscenetype ) {
6899                 // store the old scenetype
6900                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6901                 r_currentscenetype = scenetype;
6902                 // move in the new scene
6903                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6904         }
6905 }
6906
6907 /*
6908 ================
6909 R_GetScenePointer
6910 ================
6911 */
6912 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6913 {
6914         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6915         if( scenetype == r_currentscenetype ) {
6916                 return &r_refdef.scene;
6917         } else {
6918                 return &r_scenes_store[ scenetype ];
6919         }
6920 }
6921
6922 static int R_SortEntities_Compare(const void *ap, const void *bp)
6923 {
6924         const entity_render_t *a = *(const entity_render_t **)ap;
6925         const entity_render_t *b = *(const entity_render_t **)bp;
6926
6927         // 1. compare model
6928         if(a->model < b->model)
6929                 return -1;
6930         if(a->model > b->model)
6931                 return +1;
6932
6933         // 2. compare skin
6934         // TODO possibly calculate the REAL skinnum here first using
6935         // skinscenes?
6936         if(a->skinnum < b->skinnum)
6937                 return -1;
6938         if(a->skinnum > b->skinnum)
6939                 return +1;
6940
6941         // everything we compared is equal
6942         return 0;
6943 }
6944 static void R_SortEntities(void)
6945 {
6946         // below or equal 2 ents, sorting never gains anything
6947         if(r_refdef.scene.numentities <= 2)
6948                 return;
6949         // sort
6950         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6951 }
6952
6953 /*
6954 ================
6955 R_RenderView
6956 ================
6957 */
6958 int dpsoftrast_test;
6959 extern cvar_t r_shadow_bouncegrid;
6960 void R_RenderView(void)
6961 {
6962         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6963         int fbo;
6964         rtexture_t *depthtexture;
6965         rtexture_t *colortexture;
6966
6967         dpsoftrast_test = r_test.integer;
6968
6969         if (r_timereport_active)
6970                 R_TimeReport("start");
6971         r_textureframe++; // used only by R_GetCurrentTexture
6972         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6973
6974         if(R_CompileShader_CheckStaticParms())
6975                 R_GLSL_Restart_f();
6976
6977         if (!r_drawentities.integer)
6978                 r_refdef.scene.numentities = 0;
6979         else if (r_sortentities.integer)
6980                 R_SortEntities();
6981
6982         R_AnimCache_ClearCache();
6983         R_FrameData_NewFrame();
6984
6985         /* adjust for stereo display */
6986         if(R_Stereo_Active())
6987         {
6988                 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);
6989                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6990         }
6991
6992         if (r_refdef.view.isoverlay)
6993         {
6994                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6995                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6996                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6997                 R_TimeReport("depthclear");
6998
6999                 r_refdef.view.showdebug = false;
7000
7001                 r_fb.water.enabled = false;
7002                 r_fb.water.numwaterplanes = 0;
7003
7004                 R_RenderScene(0, NULL, NULL);
7005
7006                 r_refdef.view.matrix = originalmatrix;
7007
7008                 CHECKGLERROR
7009                 return;
7010         }
7011
7012         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7013         {
7014                 r_refdef.view.matrix = originalmatrix;
7015                 return;
7016         }
7017
7018         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7019
7020         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7021                 // in sRGB fallback, behave similar to true sRGB: convert this
7022                 // value from linear to sRGB
7023                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7024
7025         R_RenderView_UpdateViewVectors();
7026
7027         R_Shadow_UpdateWorldLightSelection();
7028
7029         R_Bloom_StartFrame();
7030
7031         // apply bloom brightness offset
7032         if(r_fb.bloomtexture[0])
7033                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7034
7035         R_Water_StartFrame();
7036
7037         // now we probably have an fbo to render into
7038         fbo = r_fb.fbo;
7039         depthtexture = r_fb.depthtexture;
7040         colortexture = r_fb.colortexture;
7041
7042         CHECKGLERROR
7043         if (r_timereport_active)
7044                 R_TimeReport("viewsetup");
7045
7046         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7047
7048         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7049         {
7050                 R_ClearScreen(r_refdef.fogenabled);
7051                 if (r_timereport_active)
7052                         R_TimeReport("viewclear");
7053         }
7054         r_refdef.view.clear = true;
7055
7056         r_refdef.view.showdebug = true;
7057
7058         R_View_Update();
7059         if (r_timereport_active)
7060                 R_TimeReport("visibility");
7061
7062         R_AnimCache_CacheVisibleEntities();
7063         if (r_timereport_active)
7064                 R_TimeReport("animcache");
7065
7066         R_Shadow_UpdateBounceGridTexture();
7067         if (r_timereport_active && r_shadow_bouncegrid.integer)
7068                 R_TimeReport("bouncegrid");
7069
7070         r_fb.water.numwaterplanes = 0;
7071         if (r_fb.water.enabled)
7072                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7073
7074         R_RenderScene(fbo, depthtexture, colortexture);
7075         r_fb.water.numwaterplanes = 0;
7076
7077         R_BlendView(fbo, depthtexture, colortexture);
7078         if (r_timereport_active)
7079                 R_TimeReport("blendview");
7080
7081         GL_Scissor(0, 0, vid.width, vid.height);
7082         GL_ScissorTest(false);
7083
7084         r_refdef.view.matrix = originalmatrix;
7085
7086         CHECKGLERROR
7087 }
7088
7089 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7090 {
7091         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7092         {
7093                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7094                 if (r_timereport_active)
7095                         R_TimeReport("waterworld");
7096         }
7097
7098         // don't let sound skip if going slow
7099         if (r_refdef.scene.extraupdate)
7100                 S_ExtraUpdate ();
7101
7102         R_DrawModelsAddWaterPlanes();
7103         if (r_timereport_active)
7104                 R_TimeReport("watermodels");
7105
7106         if (r_fb.water.numwaterplanes)
7107         {
7108                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7109                 if (r_timereport_active)
7110                         R_TimeReport("waterscenes");
7111         }
7112 }
7113
7114 extern cvar_t cl_locs_show;
7115 static void R_DrawLocs(void);
7116 static void R_DrawEntityBBoxes(void);
7117 static void R_DrawModelDecals(void);
7118 extern cvar_t cl_decals_newsystem;
7119 extern qboolean r_shadow_usingdeferredprepass;
7120 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7121 {
7122         qboolean shadowmapping = false;
7123
7124         if (r_timereport_active)
7125                 R_TimeReport("beginscene");
7126
7127         r_refdef.stats.renders++;
7128
7129         R_UpdateFog();
7130
7131         // don't let sound skip if going slow
7132         if (r_refdef.scene.extraupdate)
7133                 S_ExtraUpdate ();
7134
7135         R_MeshQueue_BeginScene();
7136
7137         R_SkyStartFrame();
7138
7139         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);
7140
7141         if (r_timereport_active)
7142                 R_TimeReport("skystartframe");
7143
7144         if (cl.csqc_vidvars.drawworld)
7145         {
7146                 // don't let sound skip if going slow
7147                 if (r_refdef.scene.extraupdate)
7148                         S_ExtraUpdate ();
7149
7150                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7151                 {
7152                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7153                         if (r_timereport_active)
7154                                 R_TimeReport("worldsky");
7155                 }
7156
7157                 if (R_DrawBrushModelsSky() && r_timereport_active)
7158                         R_TimeReport("bmodelsky");
7159
7160                 if (skyrendermasked && skyrenderlater)
7161                 {
7162                         // we have to force off the water clipping plane while rendering sky
7163                         R_SetupView(false, fbo, depthtexture, colortexture);
7164                         R_Sky();
7165                         R_SetupView(true, fbo, depthtexture, colortexture);
7166                         if (r_timereport_active)
7167                                 R_TimeReport("sky");
7168                 }
7169         }
7170
7171         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7172         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7173                 R_Shadow_PrepareModelShadows();
7174         if (r_timereport_active)
7175                 R_TimeReport("preparelights");
7176
7177         if (R_Shadow_ShadowMappingEnabled())
7178                 shadowmapping = true;
7179
7180         if (r_shadow_usingdeferredprepass)
7181                 R_Shadow_DrawPrepass();
7182
7183         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7184         {
7185                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7186                 if (r_timereport_active)
7187                         R_TimeReport("worlddepth");
7188         }
7189         if (r_depthfirst.integer >= 2)
7190         {
7191                 R_DrawModelsDepth();
7192                 if (r_timereport_active)
7193                         R_TimeReport("modeldepth");
7194         }
7195
7196         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7197         {
7198                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7199                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7200                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7201                 // don't let sound skip if going slow
7202                 if (r_refdef.scene.extraupdate)
7203                         S_ExtraUpdate ();
7204         }
7205
7206         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7207         {
7208                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7209                 if (r_timereport_active)
7210                         R_TimeReport("world");
7211         }
7212
7213         // don't let sound skip if going slow
7214         if (r_refdef.scene.extraupdate)
7215                 S_ExtraUpdate ();
7216
7217         R_DrawModels();
7218         if (r_timereport_active)
7219                 R_TimeReport("models");
7220
7221         // don't let sound skip if going slow
7222         if (r_refdef.scene.extraupdate)
7223                 S_ExtraUpdate ();
7224
7225         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7226         {
7227                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7228                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7229                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7230                 // don't let sound skip if going slow
7231                 if (r_refdef.scene.extraupdate)
7232                         S_ExtraUpdate ();
7233         }
7234
7235         if (!r_shadow_usingdeferredprepass)
7236         {
7237                 R_Shadow_DrawLights();
7238                 if (r_timereport_active)
7239                         R_TimeReport("rtlights");
7240         }
7241
7242         // don't let sound skip if going slow
7243         if (r_refdef.scene.extraupdate)
7244                 S_ExtraUpdate ();
7245
7246         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7247         {
7248                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7249                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7250                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7251                 // don't let sound skip if going slow
7252                 if (r_refdef.scene.extraupdate)
7253                         S_ExtraUpdate ();
7254         }
7255
7256         if (cl.csqc_vidvars.drawworld)
7257         {
7258                 if (cl_decals_newsystem.integer)
7259                 {
7260                         R_DrawModelDecals();
7261                         if (r_timereport_active)
7262                                 R_TimeReport("modeldecals");
7263                 }
7264                 else
7265                 {
7266                         R_DrawDecals();
7267                         if (r_timereport_active)
7268                                 R_TimeReport("decals");
7269                 }
7270
7271                 R_DrawParticles();
7272                 if (r_timereport_active)
7273                         R_TimeReport("particles");
7274
7275                 R_DrawExplosions();
7276                 if (r_timereport_active)
7277                         R_TimeReport("explosions");
7278
7279                 R_DrawLightningBeams();
7280                 if (r_timereport_active)
7281                         R_TimeReport("lightning");
7282         }
7283
7284         if (cl.csqc_loaded)
7285                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7286
7287         if (r_refdef.view.showdebug)
7288         {
7289                 if (cl_locs_show.integer)
7290                 {
7291                         R_DrawLocs();
7292                         if (r_timereport_active)
7293                                 R_TimeReport("showlocs");
7294                 }
7295
7296                 if (r_drawportals.integer)
7297                 {
7298                         R_DrawPortals();
7299                         if (r_timereport_active)
7300                                 R_TimeReport("portals");
7301                 }
7302
7303                 if (r_showbboxes.value > 0)
7304                 {
7305                         R_DrawEntityBBoxes();
7306                         if (r_timereport_active)
7307                                 R_TimeReport("bboxes");
7308                 }
7309         }
7310
7311         if (r_transparent.integer)
7312         {
7313                 R_MeshQueue_RenderTransparent();
7314                 if (r_timereport_active)
7315                         R_TimeReport("drawtrans");
7316         }
7317
7318         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))
7319         {
7320                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7321                 if (r_timereport_active)
7322                         R_TimeReport("worlddebug");
7323                 R_DrawModelsDebug();
7324                 if (r_timereport_active)
7325                         R_TimeReport("modeldebug");
7326         }
7327
7328         if (cl.csqc_vidvars.drawworld)
7329         {
7330                 R_Shadow_DrawCoronas();
7331                 if (r_timereport_active)
7332                         R_TimeReport("coronas");
7333         }
7334
7335 #if 0
7336         {
7337                 GL_DepthTest(false);
7338                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7339                 GL_Color(1, 1, 1, 1);
7340                 qglBegin(GL_POLYGON);
7341                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7342                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7343                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7344                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7345                 qglEnd();
7346                 qglBegin(GL_POLYGON);
7347                 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]);
7348                 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]);
7349                 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]);
7350                 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]);
7351                 qglEnd();
7352                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7353         }
7354 #endif
7355
7356         // don't let sound skip if going slow
7357         if (r_refdef.scene.extraupdate)
7358                 S_ExtraUpdate ();
7359 }
7360
7361 static const unsigned short bboxelements[36] =
7362 {
7363         5, 1, 3, 5, 3, 7,
7364         6, 2, 0, 6, 0, 4,
7365         7, 3, 2, 7, 2, 6,
7366         4, 0, 1, 4, 1, 5,
7367         4, 5, 7, 4, 7, 6,
7368         1, 0, 2, 1, 2, 3,
7369 };
7370
7371 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7372 {
7373         int i;
7374         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7375
7376         RSurf_ActiveWorldEntity();
7377
7378         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7379         GL_DepthMask(false);
7380         GL_DepthRange(0, 1);
7381         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7382 //      R_Mesh_ResetTextureState();
7383
7384         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7385         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7386         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7387         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7388         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7389         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7390         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7391         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7392         R_FillColors(color4f, 8, cr, cg, cb, ca);
7393         if (r_refdef.fogenabled)
7394         {
7395                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7396                 {
7397                         f1 = RSurf_FogVertex(v);
7398                         f2 = 1 - f1;
7399                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7400                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7401                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7402                 }
7403         }
7404         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7405         R_Mesh_ResetTextureState();
7406         R_SetupShader_Generic_NoTexture(false, false);
7407         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7408 }
7409
7410 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7411 {
7412         prvm_prog_t *prog = SVVM_prog;
7413         int i;
7414         float color[4];
7415         prvm_edict_t *edict;
7416
7417         // this function draws bounding boxes of server entities
7418         if (!sv.active)
7419                 return;
7420
7421         GL_CullFace(GL_NONE);
7422         R_SetupShader_Generic_NoTexture(false, false);
7423
7424         for (i = 0;i < numsurfaces;i++)
7425         {
7426                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7427                 switch ((int)PRVM_serveredictfloat(edict, solid))
7428                 {
7429                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7430                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7431                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7432                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7433                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7434                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7435                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7436                 }
7437                 color[3] *= r_showbboxes.value;
7438                 color[3] = bound(0, color[3], 1);
7439                 GL_DepthTest(!r_showdisabledepthtest.integer);
7440                 GL_CullFace(r_refdef.view.cullface_front);
7441                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7442         }
7443 }
7444
7445 static void R_DrawEntityBBoxes(void)
7446 {
7447         int i;
7448         prvm_edict_t *edict;
7449         vec3_t center;
7450         prvm_prog_t *prog = SVVM_prog;
7451
7452         // this function draws bounding boxes of server entities
7453         if (!sv.active)
7454                 return;
7455
7456         for (i = 0;i < prog->num_edicts;i++)
7457         {
7458                 edict = PRVM_EDICT_NUM(i);
7459                 if (edict->priv.server->free)
7460                         continue;
7461                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7462                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7463                         continue;
7464                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7465                         continue;
7466                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7467                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7468         }
7469 }
7470
7471 static const int nomodelelement3i[24] =
7472 {
7473         5, 2, 0,
7474         5, 1, 2,
7475         5, 0, 3,
7476         5, 3, 1,
7477         0, 2, 4,
7478         2, 1, 4,
7479         3, 0, 4,
7480         1, 3, 4
7481 };
7482
7483 static const unsigned short nomodelelement3s[24] =
7484 {
7485         5, 2, 0,
7486         5, 1, 2,
7487         5, 0, 3,
7488         5, 3, 1,
7489         0, 2, 4,
7490         2, 1, 4,
7491         3, 0, 4,
7492         1, 3, 4
7493 };
7494
7495 static const float nomodelvertex3f[6*3] =
7496 {
7497         -16,   0,   0,
7498          16,   0,   0,
7499           0, -16,   0,
7500           0,  16,   0,
7501           0,   0, -16,
7502           0,   0,  16
7503 };
7504
7505 static const float nomodelcolor4f[6*4] =
7506 {
7507         0.0f, 0.0f, 0.5f, 1.0f,
7508         0.0f, 0.0f, 0.5f, 1.0f,
7509         0.0f, 0.5f, 0.0f, 1.0f,
7510         0.0f, 0.5f, 0.0f, 1.0f,
7511         0.5f, 0.0f, 0.0f, 1.0f,
7512         0.5f, 0.0f, 0.0f, 1.0f
7513 };
7514
7515 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7516 {
7517         int i;
7518         float f1, f2, *c;
7519         float color4f[6*4];
7520
7521         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);
7522
7523         // this is only called once per entity so numsurfaces is always 1, and
7524         // surfacelist is always {0}, so this code does not handle batches
7525
7526         if (rsurface.ent_flags & RENDER_ADDITIVE)
7527         {
7528                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7529                 GL_DepthMask(false);
7530         }
7531         else if (rsurface.colormod[3] < 1)
7532         {
7533                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7534                 GL_DepthMask(false);
7535         }
7536         else
7537         {
7538                 GL_BlendFunc(GL_ONE, GL_ZERO);
7539                 GL_DepthMask(true);
7540         }
7541         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7542         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7543         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7544         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7545         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7546         for (i = 0, c = color4f;i < 6;i++, c += 4)
7547         {
7548                 c[0] *= rsurface.colormod[0];
7549                 c[1] *= rsurface.colormod[1];
7550                 c[2] *= rsurface.colormod[2];
7551                 c[3] *= rsurface.colormod[3];
7552         }
7553         if (r_refdef.fogenabled)
7554         {
7555                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7556                 {
7557                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7558                         f2 = 1 - f1;
7559                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7560                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7561                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7562                 }
7563         }
7564 //      R_Mesh_ResetTextureState();
7565         R_SetupShader_Generic_NoTexture(false, false);
7566         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7567         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7568 }
7569
7570 void R_DrawNoModel(entity_render_t *ent)
7571 {
7572         vec3_t org;
7573         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7574         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7575                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7576         else
7577                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7578 }
7579
7580 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7581 {
7582         vec3_t right1, right2, diff, normal;
7583
7584         VectorSubtract (org2, org1, normal);
7585
7586         // calculate 'right' vector for start
7587         VectorSubtract (r_refdef.view.origin, org1, diff);
7588         CrossProduct (normal, diff, right1);
7589         VectorNormalize (right1);
7590
7591         // calculate 'right' vector for end
7592         VectorSubtract (r_refdef.view.origin, org2, diff);
7593         CrossProduct (normal, diff, right2);
7594         VectorNormalize (right2);
7595
7596         vert[ 0] = org1[0] + width * right1[0];
7597         vert[ 1] = org1[1] + width * right1[1];
7598         vert[ 2] = org1[2] + width * right1[2];
7599         vert[ 3] = org1[0] - width * right1[0];
7600         vert[ 4] = org1[1] - width * right1[1];
7601         vert[ 5] = org1[2] - width * right1[2];
7602         vert[ 6] = org2[0] - width * right2[0];
7603         vert[ 7] = org2[1] - width * right2[1];
7604         vert[ 8] = org2[2] - width * right2[2];
7605         vert[ 9] = org2[0] + width * right2[0];
7606         vert[10] = org2[1] + width * right2[1];
7607         vert[11] = org2[2] + width * right2[2];
7608 }
7609
7610 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)
7611 {
7612         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7613         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7614         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7615         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7616         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7617         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7618         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7619         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7620         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7621         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7622         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7623         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7624 }
7625
7626 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7627 {
7628         int i;
7629         float *vertex3f;
7630         float v[3];
7631         VectorSet(v, x, y, z);
7632         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7633                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7634                         break;
7635         if (i == mesh->numvertices)
7636         {
7637                 if (mesh->numvertices < mesh->maxvertices)
7638                 {
7639                         VectorCopy(v, vertex3f);
7640                         mesh->numvertices++;
7641                 }
7642                 return mesh->numvertices;
7643         }
7644         else
7645                 return i;
7646 }
7647
7648 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7649 {
7650         int i;
7651         int *e, element[3];
7652         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7653         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7654         e = mesh->element3i + mesh->numtriangles * 3;
7655         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7656         {
7657                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7658                 if (mesh->numtriangles < mesh->maxtriangles)
7659                 {
7660                         *e++ = element[0];
7661                         *e++ = element[1];
7662                         *e++ = element[2];
7663                         mesh->numtriangles++;
7664                 }
7665                 element[1] = element[2];
7666         }
7667 }
7668
7669 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7670 {
7671         int i;
7672         int *e, element[3];
7673         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7674         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7675         e = mesh->element3i + mesh->numtriangles * 3;
7676         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7677         {
7678                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7679                 if (mesh->numtriangles < mesh->maxtriangles)
7680                 {
7681                         *e++ = element[0];
7682                         *e++ = element[1];
7683                         *e++ = element[2];
7684                         mesh->numtriangles++;
7685                 }
7686                 element[1] = element[2];
7687         }
7688 }
7689
7690 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7691 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7692 {
7693         int planenum, planenum2;
7694         int w;
7695         int tempnumpoints;
7696         mplane_t *plane, *plane2;
7697         double maxdist;
7698         double temppoints[2][256*3];
7699         // figure out how large a bounding box we need to properly compute this brush
7700         maxdist = 0;
7701         for (w = 0;w < numplanes;w++)
7702                 maxdist = max(maxdist, fabs(planes[w].dist));
7703         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7704         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7705         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7706         {
7707                 w = 0;
7708                 tempnumpoints = 4;
7709                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7710                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7711                 {
7712                         if (planenum2 == planenum)
7713                                 continue;
7714                         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);
7715                         w = !w;
7716                 }
7717                 if (tempnumpoints < 3)
7718                         continue;
7719                 // generate elements forming a triangle fan for this polygon
7720                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7721         }
7722 }
7723
7724 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)
7725 {
7726         texturelayer_t *layer;
7727         layer = t->currentlayers + t->currentnumlayers++;
7728         layer->type = type;
7729         layer->depthmask = depthmask;
7730         layer->blendfunc1 = blendfunc1;
7731         layer->blendfunc2 = blendfunc2;
7732         layer->texture = texture;
7733         layer->texmatrix = *matrix;
7734         layer->color[0] = r;
7735         layer->color[1] = g;
7736         layer->color[2] = b;
7737         layer->color[3] = a;
7738 }
7739
7740 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7741 {
7742         if(parms[0] == 0 && parms[1] == 0)
7743                 return false;
7744         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7745                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7746                         return false;
7747         return true;
7748 }
7749
7750 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7751 {
7752         double index, f;
7753         index = parms[2] + rsurface.shadertime * parms[3];
7754         index -= floor(index);
7755         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7756         {
7757         default:
7758         case Q3WAVEFUNC_NONE:
7759         case Q3WAVEFUNC_NOISE:
7760         case Q3WAVEFUNC_COUNT:
7761                 f = 0;
7762                 break;
7763         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7764         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7765         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7766         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7767         case Q3WAVEFUNC_TRIANGLE:
7768                 index *= 4;
7769                 f = index - floor(index);
7770                 if (index < 1)
7771                 {
7772                         // f = f;
7773                 }
7774                 else if (index < 2)
7775                         f = 1 - f;
7776                 else if (index < 3)
7777                         f = -f;
7778                 else
7779                         f = -(1 - f);
7780                 break;
7781         }
7782         f = parms[0] + parms[1] * f;
7783         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7784                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7785         return (float) f;
7786 }
7787
7788 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7789 {
7790         int w, h, idx;
7791         double f;
7792         double offsetd[2];
7793         float tcmat[12];
7794         matrix4x4_t matrix, temp;
7795         switch(tcmod->tcmod)
7796         {
7797                 case Q3TCMOD_COUNT:
7798                 case Q3TCMOD_NONE:
7799                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7800                                 matrix = r_waterscrollmatrix;
7801                         else
7802                                 matrix = identitymatrix;
7803                         break;
7804                 case Q3TCMOD_ENTITYTRANSLATE:
7805                         // this is used in Q3 to allow the gamecode to control texcoord
7806                         // scrolling on the entity, which is not supported in darkplaces yet.
7807                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7808                         break;
7809                 case Q3TCMOD_ROTATE:
7810                         f = tcmod->parms[0] * rsurface.shadertime;
7811                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7812                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7813                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7814                         break;
7815                 case Q3TCMOD_SCALE:
7816                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7817                         break;
7818                 case Q3TCMOD_SCROLL:
7819                         // extra care is needed because of precision breakdown with large values of time
7820                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7821                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7822                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7823                         break;
7824                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7825                         w = (int) tcmod->parms[0];
7826                         h = (int) tcmod->parms[1];
7827                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7828                         f = f - floor(f);
7829                         idx = (int) floor(f * w * h);
7830                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7831                         break;
7832                 case Q3TCMOD_STRETCH:
7833                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7834                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7835                         break;
7836                 case Q3TCMOD_TRANSFORM:
7837                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7838                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7839                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7840                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7841                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7842                         break;
7843                 case Q3TCMOD_TURBULENT:
7844                         // this is handled in the RSurf_PrepareVertices function
7845                         matrix = identitymatrix;
7846                         break;
7847         }
7848         temp = *texmatrix;
7849         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7850 }
7851
7852 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7853 {
7854         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7855         char name[MAX_QPATH];
7856         skinframe_t *skinframe;
7857         unsigned char pixels[296*194];
7858         strlcpy(cache->name, skinname, sizeof(cache->name));
7859         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7860         if (developer_loading.integer)
7861                 Con_Printf("loading %s\n", name);
7862         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7863         if (!skinframe || !skinframe->base)
7864         {
7865                 unsigned char *f;
7866                 fs_offset_t filesize;
7867                 skinframe = NULL;
7868                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7869                 if (f)
7870                 {
7871                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7872                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7873                         Mem_Free(f);
7874                 }
7875         }
7876         cache->skinframe = skinframe;
7877 }
7878
7879 texture_t *R_GetCurrentTexture(texture_t *t)
7880 {
7881         int i;
7882         const entity_render_t *ent = rsurface.entity;
7883         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7884         q3shaderinfo_layer_tcmod_t *tcmod;
7885
7886         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7887                 return t->currentframe;
7888         t->update_lastrenderframe = r_textureframe;
7889         t->update_lastrenderentity = (void *)ent;
7890
7891         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7892                 t->camera_entity = ent->entitynumber;
7893         else
7894                 t->camera_entity = 0;
7895
7896         // switch to an alternate material if this is a q1bsp animated material
7897         {
7898                 texture_t *texture = t;
7899                 int s = rsurface.ent_skinnum;
7900                 if ((unsigned int)s >= (unsigned int)model->numskins)
7901                         s = 0;
7902                 if (model->skinscenes)
7903                 {
7904                         if (model->skinscenes[s].framecount > 1)
7905                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7906                         else
7907                                 s = model->skinscenes[s].firstframe;
7908                 }
7909                 if (s > 0)
7910                         t = t + s * model->num_surfaces;
7911                 if (t->animated)
7912                 {
7913                         // use an alternate animation if the entity's frame is not 0,
7914                         // and only if the texture has an alternate animation
7915                         if (rsurface.ent_alttextures && t->anim_total[1])
7916                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7917                         else
7918                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7919                 }
7920                 texture->currentframe = t;
7921         }
7922
7923         // update currentskinframe to be a qw skin or animation frame
7924         if (rsurface.ent_qwskin >= 0)
7925         {
7926                 i = rsurface.ent_qwskin;
7927                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7928                 {
7929                         r_qwskincache_size = cl.maxclients;
7930                         if (r_qwskincache)
7931                                 Mem_Free(r_qwskincache);
7932                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7933                 }
7934                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7935                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7936                 t->currentskinframe = r_qwskincache[i].skinframe;
7937                 if (t->currentskinframe == NULL)
7938                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7939         }
7940         else if (t->numskinframes >= 2)
7941                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7942         if (t->backgroundnumskinframes >= 2)
7943                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7944
7945         t->currentmaterialflags = t->basematerialflags;
7946         t->currentalpha = rsurface.colormod[3];
7947         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7948                 t->currentalpha *= r_wateralpha.value;
7949         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7950                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7951         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7952                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7953         if (!(rsurface.ent_flags & RENDER_LIGHT))
7954                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7955         else if (FAKELIGHT_ENABLED)
7956         {
7957                 // no modellight if using fakelight for the map
7958         }
7959         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7960         {
7961                 // pick a model lighting mode
7962                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7963                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7964                 else
7965                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7966         }
7967         if (rsurface.ent_flags & RENDER_ADDITIVE)
7968                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7969         else if (t->currentalpha < 1)
7970                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7971         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7972         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7973                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7974         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7975                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7976         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7977                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7978         if (t->backgroundnumskinframes)
7979                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7980         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7981         {
7982                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7983                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7984         }
7985         else
7986                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7987         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7988         {
7989                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7990                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7991         }
7992         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7993                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7994
7995         // there is no tcmod
7996         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7997         {
7998                 t->currenttexmatrix = r_waterscrollmatrix;
7999                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8000         }
8001         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8002         {
8003                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8004                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8005         }
8006
8007         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8008                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8009         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8010                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8011
8012         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8013         if (t->currentskinframe->qpixels)
8014                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8015         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8016         if (!t->basetexture)
8017                 t->basetexture = r_texture_notexture;
8018         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8019         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8020         t->nmaptexture = t->currentskinframe->nmap;
8021         if (!t->nmaptexture)
8022                 t->nmaptexture = r_texture_blanknormalmap;
8023         t->glosstexture = r_texture_black;
8024         t->glowtexture = t->currentskinframe->glow;
8025         t->fogtexture = t->currentskinframe->fog;
8026         t->reflectmasktexture = t->currentskinframe->reflect;
8027         if (t->backgroundnumskinframes)
8028         {
8029                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8030                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8031                 t->backgroundglosstexture = r_texture_black;
8032                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8033                 if (!t->backgroundnmaptexture)
8034                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8035                 // make sure that if glow is going to be used, both textures are not NULL
8036                 if (!t->backgroundglowtexture && t->glowtexture)
8037                         t->backgroundglowtexture = r_texture_black;
8038                 if (!t->glowtexture && t->backgroundglowtexture)
8039                         t->glowtexture = r_texture_black;
8040         }
8041         else
8042         {
8043                 t->backgroundbasetexture = r_texture_white;
8044                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8045                 t->backgroundglosstexture = r_texture_black;
8046                 t->backgroundglowtexture = NULL;
8047         }
8048         t->specularpower = r_shadow_glossexponent.value;
8049         // TODO: store reference values for these in the texture?
8050         t->specularscale = 0;
8051         if (r_shadow_gloss.integer > 0)
8052         {
8053                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8054                 {
8055                         if (r_shadow_glossintensity.value > 0)
8056                         {
8057                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8058                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8059                                 t->specularscale = r_shadow_glossintensity.value;
8060                         }
8061                 }
8062                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8063                 {
8064                         t->glosstexture = r_texture_white;
8065                         t->backgroundglosstexture = r_texture_white;
8066                         t->specularscale = r_shadow_gloss2intensity.value;
8067                         t->specularpower = r_shadow_gloss2exponent.value;
8068                 }
8069         }
8070         t->specularscale *= t->specularscalemod;
8071         t->specularpower *= t->specularpowermod;
8072         t->rtlightambient = 0;
8073
8074         // lightmaps mode looks bad with dlights using actual texturing, so turn
8075         // off the colormap and glossmap, but leave the normalmap on as it still
8076         // accurately represents the shading involved
8077         if (gl_lightmaps.integer)
8078         {
8079                 t->basetexture = r_texture_grey128;
8080                 t->pantstexture = r_texture_black;
8081                 t->shirttexture = r_texture_black;
8082                 if (gl_lightmaps.integer < 2)
8083                         t->nmaptexture = r_texture_blanknormalmap;
8084                 t->glosstexture = r_texture_black;
8085                 t->glowtexture = NULL;
8086                 t->fogtexture = NULL;
8087                 t->reflectmasktexture = NULL;
8088                 t->backgroundbasetexture = NULL;
8089                 if (gl_lightmaps.integer < 2)
8090                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8091                 t->backgroundglosstexture = r_texture_black;
8092                 t->backgroundglowtexture = NULL;
8093                 t->specularscale = 0;
8094                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8095         }
8096
8097         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8098         VectorClear(t->dlightcolor);
8099         t->currentnumlayers = 0;
8100         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8101         {
8102                 int blendfunc1, blendfunc2;
8103                 qboolean depthmask;
8104                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8105                 {
8106                         blendfunc1 = GL_SRC_ALPHA;
8107                         blendfunc2 = GL_ONE;
8108                 }
8109                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8110                 {
8111                         blendfunc1 = GL_SRC_ALPHA;
8112                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8113                 }
8114                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8115                 {
8116                         blendfunc1 = t->customblendfunc[0];
8117                         blendfunc2 = t->customblendfunc[1];
8118                 }
8119                 else
8120                 {
8121                         blendfunc1 = GL_ONE;
8122                         blendfunc2 = GL_ZERO;
8123                 }
8124                 // don't colormod evilblend textures
8125                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8126                         VectorSet(t->lightmapcolor, 1, 1, 1);
8127                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8128                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8129                 {
8130                         // fullbright is not affected by r_refdef.lightmapintensity
8131                         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]);
8132                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8133                                 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]);
8134                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8135                                 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]);
8136                 }
8137                 else
8138                 {
8139                         vec3_t ambientcolor;
8140                         float colorscale;
8141                         // set the color tint used for lights affecting this surface
8142                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8143                         colorscale = 2;
8144                         // q3bsp has no lightmap updates, so the lightstylevalue that
8145                         // would normally be baked into the lightmap must be
8146                         // applied to the color
8147                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8148                         if (model->type == mod_brushq3)
8149                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8150                         colorscale *= r_refdef.lightmapintensity;
8151                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8152                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8153                         // basic lit geometry
8154                         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]);
8155                         // add pants/shirt if needed
8156                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8157                                 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]);
8158                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8159                                 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]);
8160                         // now add ambient passes if needed
8161                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8162                         {
8163                                 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]);
8164                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8165                                         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]);
8166                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8167                                         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]);
8168                         }
8169                 }
8170                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8171                         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]);
8172                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8173                 {
8174                         // if this is opaque use alpha blend which will darken the earlier
8175                         // passes cheaply.
8176                         //
8177                         // if this is an alpha blended material, all the earlier passes
8178                         // were darkened by fog already, so we only need to add the fog
8179                         // color ontop through the fog mask texture
8180                         //
8181                         // if this is an additive blended material, all the earlier passes
8182                         // were darkened by fog already, and we should not add fog color
8183                         // (because the background was not darkened, there is no fog color
8184                         // that was lost behind it).
8185                         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]);
8186                 }
8187         }
8188
8189         return t->currentframe;
8190 }
8191
8192 rsurfacestate_t rsurface;
8193
8194 void RSurf_ActiveWorldEntity(void)
8195 {
8196         dp_model_t *model = r_refdef.scene.worldmodel;
8197         //if (rsurface.entity == r_refdef.scene.worldentity)
8198         //      return;
8199         rsurface.entity = r_refdef.scene.worldentity;
8200         rsurface.skeleton = NULL;
8201         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8202         rsurface.ent_skinnum = 0;
8203         rsurface.ent_qwskin = -1;
8204         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8205         rsurface.shadertime = r_refdef.scene.time;
8206         rsurface.matrix = identitymatrix;
8207         rsurface.inversematrix = identitymatrix;
8208         rsurface.matrixscale = 1;
8209         rsurface.inversematrixscale = 1;
8210         R_EntityMatrix(&identitymatrix);
8211         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8212         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8213         rsurface.fograngerecip = r_refdef.fograngerecip;
8214         rsurface.fogheightfade = r_refdef.fogheightfade;
8215         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8216         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8217         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8218         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8219         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8220         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8221         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8222         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8223         rsurface.colormod[3] = 1;
8224         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);
8225         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8226         rsurface.frameblend[0].lerp = 1;
8227         rsurface.ent_alttextures = false;
8228         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8229         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8230         rsurface.entityskeletaltransform3x4 = NULL;
8231         rsurface.entityskeletalnumtransforms = 0;
8232         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8233         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8234         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8235         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8236         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8237         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8238         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8239         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8240         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8241         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8242         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8243         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8244         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8245         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8246         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8247         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8248         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8249         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8250         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8251         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8252         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8253         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8254         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8255         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8256         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8257         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8258         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8259         rsurface.modelelement3i = model->surfmesh.data_element3i;
8260         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8261         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8262         rsurface.modelelement3s = model->surfmesh.data_element3s;
8263         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8264         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8265         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8266         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8267         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8268         rsurface.modelsurfaces = model->data_surfaces;
8269         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8270         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8271         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8272         rsurface.modelgeneratedvertex = false;
8273         rsurface.batchgeneratedvertex = false;
8274         rsurface.batchfirstvertex = 0;
8275         rsurface.batchnumvertices = 0;
8276         rsurface.batchfirsttriangle = 0;
8277         rsurface.batchnumtriangles = 0;
8278         rsurface.batchvertex3f  = NULL;
8279         rsurface.batchvertex3f_vertexbuffer = NULL;
8280         rsurface.batchvertex3f_bufferoffset = 0;
8281         rsurface.batchsvector3f = NULL;
8282         rsurface.batchsvector3f_vertexbuffer = NULL;
8283         rsurface.batchsvector3f_bufferoffset = 0;
8284         rsurface.batchtvector3f = NULL;
8285         rsurface.batchtvector3f_vertexbuffer = NULL;
8286         rsurface.batchtvector3f_bufferoffset = 0;
8287         rsurface.batchnormal3f  = NULL;
8288         rsurface.batchnormal3f_vertexbuffer = NULL;
8289         rsurface.batchnormal3f_bufferoffset = 0;
8290         rsurface.batchlightmapcolor4f = NULL;
8291         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8292         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8293         rsurface.batchtexcoordtexture2f = NULL;
8294         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8295         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8296         rsurface.batchtexcoordlightmap2f = NULL;
8297         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8298         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8299         rsurface.batchskeletalindex4ub = NULL;
8300         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8301         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8302         rsurface.batchskeletalweight4ub = NULL;
8303         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8304         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8305         rsurface.batchvertexmesh = NULL;
8306         rsurface.batchvertexmeshbuffer = NULL;
8307         rsurface.batchvertex3fbuffer = NULL;
8308         rsurface.batchelement3i = NULL;
8309         rsurface.batchelement3i_indexbuffer = NULL;
8310         rsurface.batchelement3i_bufferoffset = 0;
8311         rsurface.batchelement3s = NULL;
8312         rsurface.batchelement3s_indexbuffer = NULL;
8313         rsurface.batchelement3s_bufferoffset = 0;
8314         rsurface.passcolor4f = NULL;
8315         rsurface.passcolor4f_vertexbuffer = NULL;
8316         rsurface.passcolor4f_bufferoffset = 0;
8317         rsurface.forcecurrenttextureupdate = false;
8318 }
8319
8320 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8321 {
8322         dp_model_t *model = ent->model;
8323         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8324         //      return;
8325         rsurface.entity = (entity_render_t *)ent;
8326         rsurface.skeleton = ent->skeleton;
8327         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8328         rsurface.ent_skinnum = ent->skinnum;
8329         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;
8330         rsurface.ent_flags = ent->flags;
8331         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8332         rsurface.matrix = ent->matrix;
8333         rsurface.inversematrix = ent->inversematrix;
8334         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8335         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8336         R_EntityMatrix(&rsurface.matrix);
8337         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8338         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8339         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8340         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8341         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8342         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8343         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8344         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8345         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8346         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8347         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8348         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8349         rsurface.colormod[3] = ent->alpha;
8350         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8351         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8352         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8353         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8354         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8355         if (ent->model->brush.submodel && !prepass)
8356         {
8357                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8358                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8359         }
8360         // if the animcache code decided it should use the shader path, skip the deform step
8361         rsurface.entityskeletaltransform3x4 = ent->animcache_vertex3f ? NULL : ent->animcache_skeletaltransform3x4;
8362         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8363         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8364         {
8365                 if (ent->animcache_vertex3f)
8366                 {
8367                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8368                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8369                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8370                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8371                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8372                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8373                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8374                 }
8375                 else if (wanttangents)
8376                 {
8377                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8378                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8379                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8380                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8381                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8382                         rsurface.modelvertexmesh = NULL;
8383                         rsurface.modelvertexmeshbuffer = NULL;
8384                         rsurface.modelvertex3fbuffer = NULL;
8385                 }
8386                 else if (wantnormals)
8387                 {
8388                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8389                         rsurface.modelsvector3f = NULL;
8390                         rsurface.modeltvector3f = NULL;
8391                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8392                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8393                         rsurface.modelvertexmesh = NULL;
8394                         rsurface.modelvertexmeshbuffer = NULL;
8395                         rsurface.modelvertex3fbuffer = NULL;
8396                 }
8397                 else
8398                 {
8399                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8400                         rsurface.modelsvector3f = NULL;
8401                         rsurface.modeltvector3f = NULL;
8402                         rsurface.modelnormal3f = NULL;
8403                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8404                         rsurface.modelvertexmesh = NULL;
8405                         rsurface.modelvertexmeshbuffer = NULL;
8406                         rsurface.modelvertex3fbuffer = NULL;
8407                 }
8408                 rsurface.modelvertex3f_vertexbuffer = 0;
8409                 rsurface.modelvertex3f_bufferoffset = 0;
8410                 rsurface.modelsvector3f_vertexbuffer = 0;
8411                 rsurface.modelsvector3f_bufferoffset = 0;
8412                 rsurface.modeltvector3f_vertexbuffer = 0;
8413                 rsurface.modeltvector3f_bufferoffset = 0;
8414                 rsurface.modelnormal3f_vertexbuffer = 0;
8415                 rsurface.modelnormal3f_bufferoffset = 0;
8416                 rsurface.modelgeneratedvertex = true;
8417         }
8418         else
8419         {
8420                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8421                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8422                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8423                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8424                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8425                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8426                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8427                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8428                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8429                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8430                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8431                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8432                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8433                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8434                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8435                 rsurface.modelgeneratedvertex = false;
8436         }
8437         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8438         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8439         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8440         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8441         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8442         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8443         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8444         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8445         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8446         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8447         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8448         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8449         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8450         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8451         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8452         rsurface.modelelement3i = model->surfmesh.data_element3i;
8453         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8454         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8455         rsurface.modelelement3s = model->surfmesh.data_element3s;
8456         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8457         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8458         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8459         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8460         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8461         rsurface.modelsurfaces = model->data_surfaces;
8462         rsurface.batchgeneratedvertex = false;
8463         rsurface.batchfirstvertex = 0;
8464         rsurface.batchnumvertices = 0;
8465         rsurface.batchfirsttriangle = 0;
8466         rsurface.batchnumtriangles = 0;
8467         rsurface.batchvertex3f  = NULL;
8468         rsurface.batchvertex3f_vertexbuffer = NULL;
8469         rsurface.batchvertex3f_bufferoffset = 0;
8470         rsurface.batchsvector3f = NULL;
8471         rsurface.batchsvector3f_vertexbuffer = NULL;
8472         rsurface.batchsvector3f_bufferoffset = 0;
8473         rsurface.batchtvector3f = NULL;
8474         rsurface.batchtvector3f_vertexbuffer = NULL;
8475         rsurface.batchtvector3f_bufferoffset = 0;
8476         rsurface.batchnormal3f  = NULL;
8477         rsurface.batchnormal3f_vertexbuffer = NULL;
8478         rsurface.batchnormal3f_bufferoffset = 0;
8479         rsurface.batchlightmapcolor4f = NULL;
8480         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8481         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8482         rsurface.batchtexcoordtexture2f = NULL;
8483         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8484         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8485         rsurface.batchtexcoordlightmap2f = NULL;
8486         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8487         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8488         rsurface.batchskeletalindex4ub = NULL;
8489         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8490         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8491         rsurface.batchskeletalweight4ub = NULL;
8492         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8493         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8494         rsurface.batchvertexmesh = NULL;
8495         rsurface.batchvertexmeshbuffer = NULL;
8496         rsurface.batchvertex3fbuffer = NULL;
8497         rsurface.batchelement3i = NULL;
8498         rsurface.batchelement3i_indexbuffer = NULL;
8499         rsurface.batchelement3i_bufferoffset = 0;
8500         rsurface.batchelement3s = NULL;
8501         rsurface.batchelement3s_indexbuffer = NULL;
8502         rsurface.batchelement3s_bufferoffset = 0;
8503         rsurface.passcolor4f = NULL;
8504         rsurface.passcolor4f_vertexbuffer = NULL;
8505         rsurface.passcolor4f_bufferoffset = 0;
8506         rsurface.forcecurrenttextureupdate = false;
8507 }
8508
8509 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)
8510 {
8511         rsurface.entity = r_refdef.scene.worldentity;
8512         rsurface.skeleton = NULL;
8513         rsurface.ent_skinnum = 0;
8514         rsurface.ent_qwskin = -1;
8515         rsurface.ent_flags = entflags;
8516         rsurface.shadertime = r_refdef.scene.time - shadertime;
8517         rsurface.modelnumvertices = numvertices;
8518         rsurface.modelnumtriangles = numtriangles;
8519         rsurface.matrix = *matrix;
8520         rsurface.inversematrix = *inversematrix;
8521         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8522         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8523         R_EntityMatrix(&rsurface.matrix);
8524         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8525         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8526         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8527         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8528         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8529         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8530         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8531         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8532         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8533         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8534         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8535         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8536         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);
8537         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8538         rsurface.frameblend[0].lerp = 1;
8539         rsurface.ent_alttextures = false;
8540         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8541         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8542         rsurface.entityskeletaltransform3x4 = NULL;
8543         rsurface.entityskeletalnumtransforms = 0;
8544         if (wanttangents)
8545         {
8546                 rsurface.modelvertex3f = (float *)vertex3f;
8547                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8548                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8549                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8550         }
8551         else if (wantnormals)
8552         {
8553                 rsurface.modelvertex3f = (float *)vertex3f;
8554                 rsurface.modelsvector3f = NULL;
8555                 rsurface.modeltvector3f = NULL;
8556                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8557         }
8558         else
8559         {
8560                 rsurface.modelvertex3f = (float *)vertex3f;
8561                 rsurface.modelsvector3f = NULL;
8562                 rsurface.modeltvector3f = NULL;
8563                 rsurface.modelnormal3f = NULL;
8564         }
8565         rsurface.modelvertexmesh = NULL;
8566         rsurface.modelvertexmeshbuffer = NULL;
8567         rsurface.modelvertex3fbuffer = NULL;
8568         rsurface.modelvertex3f_vertexbuffer = 0;
8569         rsurface.modelvertex3f_bufferoffset = 0;
8570         rsurface.modelsvector3f_vertexbuffer = 0;
8571         rsurface.modelsvector3f_bufferoffset = 0;
8572         rsurface.modeltvector3f_vertexbuffer = 0;
8573         rsurface.modeltvector3f_bufferoffset = 0;
8574         rsurface.modelnormal3f_vertexbuffer = 0;
8575         rsurface.modelnormal3f_bufferoffset = 0;
8576         rsurface.modelgeneratedvertex = true;
8577         rsurface.modellightmapcolor4f  = (float *)color4f;
8578         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8579         rsurface.modellightmapcolor4f_bufferoffset = 0;
8580         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8581         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8582         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8583         rsurface.modeltexcoordlightmap2f  = NULL;
8584         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8585         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8586         rsurface.modelskeletalindex4ub = NULL;
8587         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8588         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8589         rsurface.modelskeletalweight4ub = NULL;
8590         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8591         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8592         rsurface.modelelement3i = (int *)element3i;
8593         rsurface.modelelement3i_indexbuffer = NULL;
8594         rsurface.modelelement3i_bufferoffset = 0;
8595         rsurface.modelelement3s = (unsigned short *)element3s;
8596         rsurface.modelelement3s_indexbuffer = NULL;
8597         rsurface.modelelement3s_bufferoffset = 0;
8598         rsurface.modellightmapoffsets = NULL;
8599         rsurface.modelsurfaces = NULL;
8600         rsurface.batchgeneratedvertex = false;
8601         rsurface.batchfirstvertex = 0;
8602         rsurface.batchnumvertices = 0;
8603         rsurface.batchfirsttriangle = 0;
8604         rsurface.batchnumtriangles = 0;
8605         rsurface.batchvertex3f  = NULL;
8606         rsurface.batchvertex3f_vertexbuffer = NULL;
8607         rsurface.batchvertex3f_bufferoffset = 0;
8608         rsurface.batchsvector3f = NULL;
8609         rsurface.batchsvector3f_vertexbuffer = NULL;
8610         rsurface.batchsvector3f_bufferoffset = 0;
8611         rsurface.batchtvector3f = NULL;
8612         rsurface.batchtvector3f_vertexbuffer = NULL;
8613         rsurface.batchtvector3f_bufferoffset = 0;
8614         rsurface.batchnormal3f  = NULL;
8615         rsurface.batchnormal3f_vertexbuffer = NULL;
8616         rsurface.batchnormal3f_bufferoffset = 0;
8617         rsurface.batchlightmapcolor4f = NULL;
8618         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8619         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8620         rsurface.batchtexcoordtexture2f = NULL;
8621         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8622         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8623         rsurface.batchtexcoordlightmap2f = NULL;
8624         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8625         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8626         rsurface.batchskeletalindex4ub = NULL;
8627         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8628         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8629         rsurface.batchskeletalweight4ub = NULL;
8630         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8631         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8632         rsurface.batchvertexmesh = NULL;
8633         rsurface.batchvertexmeshbuffer = NULL;
8634         rsurface.batchvertex3fbuffer = NULL;
8635         rsurface.batchelement3i = NULL;
8636         rsurface.batchelement3i_indexbuffer = NULL;
8637         rsurface.batchelement3i_bufferoffset = 0;
8638         rsurface.batchelement3s = NULL;
8639         rsurface.batchelement3s_indexbuffer = NULL;
8640         rsurface.batchelement3s_bufferoffset = 0;
8641         rsurface.passcolor4f = NULL;
8642         rsurface.passcolor4f_vertexbuffer = NULL;
8643         rsurface.passcolor4f_bufferoffset = 0;
8644         rsurface.forcecurrenttextureupdate = true;
8645
8646         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8647         {
8648                 if ((wantnormals || wanttangents) && !normal3f)
8649                 {
8650                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8651                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8652                 }
8653                 if (wanttangents && !svector3f)
8654                 {
8655                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8656                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8657                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8658                 }
8659         }
8660 }
8661
8662 float RSurf_FogPoint(const float *v)
8663 {
8664         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8665         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8666         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8667         float FogHeightFade = r_refdef.fogheightfade;
8668         float fogfrac;
8669         unsigned int fogmasktableindex;
8670         if (r_refdef.fogplaneviewabove)
8671                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8672         else
8673                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8674         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8675         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8676 }
8677
8678 float RSurf_FogVertex(const float *v)
8679 {
8680         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8681         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8682         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8683         float FogHeightFade = rsurface.fogheightfade;
8684         float fogfrac;
8685         unsigned int fogmasktableindex;
8686         if (r_refdef.fogplaneviewabove)
8687                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8688         else
8689                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8690         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8691         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8692 }
8693
8694 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8695 {
8696         int i;
8697         for (i = 0;i < numelements;i++)
8698                 outelement3i[i] = inelement3i[i] + adjust;
8699 }
8700
8701 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8702 extern cvar_t gl_vbo;
8703 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8704 {
8705         int deformindex;
8706         int firsttriangle;
8707         int numtriangles;
8708         int firstvertex;
8709         int endvertex;
8710         int numvertices;
8711         int surfacefirsttriangle;
8712         int surfacenumtriangles;
8713         int surfacefirstvertex;
8714         int surfaceendvertex;
8715         int surfacenumvertices;
8716         int batchnumvertices;
8717         int batchnumtriangles;
8718         int needsupdate;
8719         int i, j;
8720         qboolean gaps;
8721         qboolean dynamicvertex;
8722         float amplitude;
8723         float animpos;
8724         float scale;
8725         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8726         float waveparms[4];
8727         unsigned char *ub;
8728         q3shaderinfo_deform_t *deform;
8729         const msurface_t *surface, *firstsurface;
8730         r_vertexmesh_t *vertexmesh;
8731         if (!texturenumsurfaces)
8732                 return;
8733         // find vertex range of this surface batch
8734         gaps = false;
8735         firstsurface = texturesurfacelist[0];
8736         firsttriangle = firstsurface->num_firsttriangle;
8737         batchnumvertices = 0;
8738         batchnumtriangles = 0;
8739         firstvertex = endvertex = firstsurface->num_firstvertex;
8740         for (i = 0;i < texturenumsurfaces;i++)
8741         {
8742                 surface = texturesurfacelist[i];
8743                 if (surface != firstsurface + i)
8744                         gaps = true;
8745                 surfacefirstvertex = surface->num_firstvertex;
8746                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8747                 surfacenumvertices = surface->num_vertices;
8748                 surfacenumtriangles = surface->num_triangles;
8749                 if (firstvertex > surfacefirstvertex)
8750                         firstvertex = surfacefirstvertex;
8751                 if (endvertex < surfaceendvertex)
8752                         endvertex = surfaceendvertex;
8753                 batchnumvertices += surfacenumvertices;
8754                 batchnumtriangles += surfacenumtriangles;
8755         }
8756
8757         // we now know the vertex range used, and if there are any gaps in it
8758         rsurface.batchfirstvertex = firstvertex;
8759         rsurface.batchnumvertices = endvertex - firstvertex;
8760         rsurface.batchfirsttriangle = firsttriangle;
8761         rsurface.batchnumtriangles = batchnumtriangles;
8762
8763         // this variable holds flags for which properties have been updated that
8764         // may require regenerating vertexmesh array...
8765         needsupdate = 0;
8766
8767         // check if any dynamic vertex processing must occur
8768         dynamicvertex = false;
8769
8770         // a cvar to force the dynamic vertex path to be taken, for debugging
8771         if (r_batch_debugdynamicvertexpath.integer)
8772                 dynamicvertex = true;
8773
8774         // if there is a chance of animated vertex colors, it's a dynamic batch
8775         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8776         {
8777                 dynamicvertex = true;
8778                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8779         }
8780
8781         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8782         {
8783                 switch (deform->deform)
8784                 {
8785                 default:
8786                 case Q3DEFORM_PROJECTIONSHADOW:
8787                 case Q3DEFORM_TEXT0:
8788                 case Q3DEFORM_TEXT1:
8789                 case Q3DEFORM_TEXT2:
8790                 case Q3DEFORM_TEXT3:
8791                 case Q3DEFORM_TEXT4:
8792                 case Q3DEFORM_TEXT5:
8793                 case Q3DEFORM_TEXT6:
8794                 case Q3DEFORM_TEXT7:
8795                 case Q3DEFORM_NONE:
8796                         break;
8797                 case Q3DEFORM_AUTOSPRITE:
8798                         dynamicvertex = true;
8799                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8800                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8801                         break;
8802                 case Q3DEFORM_AUTOSPRITE2:
8803                         dynamicvertex = true;
8804                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8805                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8806                         break;
8807                 case Q3DEFORM_NORMAL:
8808                         dynamicvertex = true;
8809                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8810                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8811                         break;
8812                 case Q3DEFORM_WAVE:
8813                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8814                                 break; // if wavefunc is a nop, ignore this transform
8815                         dynamicvertex = true;
8816                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8817                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8818                         break;
8819                 case Q3DEFORM_BULGE:
8820                         dynamicvertex = true;
8821                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8822                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8823                         break;
8824                 case Q3DEFORM_MOVE:
8825                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8826                                 break; // if wavefunc is a nop, ignore this transform
8827                         dynamicvertex = true;
8828                         batchneed |= BATCHNEED_ARRAY_VERTEX;
8829                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8830                         break;
8831                 }
8832         }
8833         switch(rsurface.texture->tcgen.tcgen)
8834         {
8835         default:
8836         case Q3TCGEN_TEXTURE:
8837                 break;
8838         case Q3TCGEN_LIGHTMAP:
8839                 dynamicvertex = true;
8840                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8841                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8842                 break;
8843         case Q3TCGEN_VECTOR:
8844                 dynamicvertex = true;
8845                 batchneed |= BATCHNEED_ARRAY_VERTEX;
8846                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8847                 break;
8848         case Q3TCGEN_ENVIRONMENT:
8849                 dynamicvertex = true;
8850                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
8851                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8852                 break;
8853         }
8854         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8855         {
8856                 dynamicvertex = true;
8857                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8858                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8859         }
8860
8861         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8862         {
8863                 dynamicvertex = true;
8864                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8865         }
8866
8867         // when the model data has no vertex buffer (dynamic mesh), we need to
8868         // eliminate gaps
8869         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8870                 batchneed |= BATCHNEED_NOGAPS;
8871
8872         // the caller can specify BATCHNEED_NOGAPS to force a batch with
8873         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
8874         // we ensure this by treating the vertex batch as dynamic...
8875         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
8876                 dynamicvertex = true;
8877
8878         if (dynamicvertex)
8879         {
8880                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8881                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8882                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8883                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8884                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8885                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8886                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8887                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
8888         }
8889
8890         // if needsupdate, we have to do a dynamic vertex batch for sure
8891         if (needsupdate & batchneed)
8892                 dynamicvertex = true;
8893
8894         // see if we need to build vertexmesh from arrays
8895         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8896                 dynamicvertex = true;
8897
8898         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
8899         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
8900                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
8901
8902         rsurface.batchvertex3f = rsurface.modelvertex3f;
8903         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8904         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8905         rsurface.batchsvector3f = rsurface.modelsvector3f;
8906         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8907         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8908         rsurface.batchtvector3f = rsurface.modeltvector3f;
8909         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8910         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8911         rsurface.batchnormal3f = rsurface.modelnormal3f;
8912         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8913         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8914         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8915         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8916         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8917         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8918         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8919         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8920         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8921         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8922         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8923         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
8924         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
8925         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
8926         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
8927         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
8928         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
8929         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8930         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8931         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8932         rsurface.batchelement3i = rsurface.modelelement3i;
8933         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8934         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8935         rsurface.batchelement3s = rsurface.modelelement3s;
8936         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8937         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8938         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
8939         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
8940
8941         // if any dynamic vertex processing has to occur in software, we copy the
8942         // entire surface list together before processing to rebase the vertices
8943         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8944         //
8945         // if any gaps exist and we do not have a static vertex buffer, we have to
8946         // copy the surface list together to avoid wasting upload bandwidth on the
8947         // vertices in the gaps.
8948         //
8949         // if gaps exist and we have a static vertex buffer, we can choose whether
8950         // to combine the index buffer ranges into one dynamic index buffer or
8951         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
8952         //
8953         // in many cases the batch is reduced to one draw call.
8954
8955         rsurface.batchmultidraw = false;
8956         rsurface.batchmultidrawnumsurfaces = 0;
8957         rsurface.batchmultidrawsurfacelist = NULL;
8958
8959         if (!dynamicvertex)
8960         {
8961                 // static vertex data, just set pointers...
8962                 rsurface.batchgeneratedvertex = false;
8963                 // if there are gaps, we want to build a combined index buffer,
8964                 // otherwise use the original static buffer with an appropriate offset
8965                 if (gaps)
8966                 {
8967                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
8968                         {
8969                                 rsurface.batchmultidraw = true;
8970                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
8971                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
8972                                 return;
8973                         }
8974                         // build a new triangle elements array for this batch
8975                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8976                         rsurface.batchfirsttriangle = 0;
8977                         numtriangles = 0;
8978                         for (i = 0;i < texturenumsurfaces;i++)
8979                         {
8980                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8981                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8982                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8983                                 numtriangles += surfacenumtriangles;
8984                         }
8985                         rsurface.batchelement3i_indexbuffer = NULL;
8986                         rsurface.batchelement3i_bufferoffset = 0;
8987                         rsurface.batchelement3s = NULL;
8988                         rsurface.batchelement3s_indexbuffer = NULL;
8989                         rsurface.batchelement3s_bufferoffset = 0;
8990                         if (endvertex <= 65536)
8991                         {
8992                                 // make a 16bit (unsigned short) index array if possible
8993                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8994                                 for (i = 0;i < numtriangles*3;i++)
8995                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8996                         }
8997                 }
8998                 return;
8999         }
9000
9001         // something needs software processing, do it for real...
9002         // we only directly handle separate array data in this case and then
9003         // generate interleaved data if needed...
9004         rsurface.batchgeneratedvertex = true;
9005
9006         // now copy the vertex data into a combined array and make an index array
9007         // (this is what Quake3 does all the time)
9008         // we also apply any skeletal animation here that would have been done in
9009         // the vertex shader, because most of the dynamic vertex animation cases
9010         // need actual vertex positions and normals
9011         //if (dynamicvertex)
9012         {
9013                 rsurface.batchvertex3fbuffer = NULL;
9014                 rsurface.batchvertexmesh = NULL;
9015                 rsurface.batchvertexmeshbuffer = NULL;
9016                 rsurface.batchvertex3f = NULL;
9017                 rsurface.batchvertex3f_vertexbuffer = NULL;
9018                 rsurface.batchvertex3f_bufferoffset = 0;
9019                 rsurface.batchsvector3f = NULL;
9020                 rsurface.batchsvector3f_vertexbuffer = NULL;
9021                 rsurface.batchsvector3f_bufferoffset = 0;
9022                 rsurface.batchtvector3f = NULL;
9023                 rsurface.batchtvector3f_vertexbuffer = NULL;
9024                 rsurface.batchtvector3f_bufferoffset = 0;
9025                 rsurface.batchnormal3f = NULL;
9026                 rsurface.batchnormal3f_vertexbuffer = NULL;
9027                 rsurface.batchnormal3f_bufferoffset = 0;
9028                 rsurface.batchlightmapcolor4f = NULL;
9029                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9030                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9031                 rsurface.batchtexcoordtexture2f = NULL;
9032                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9033                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9034                 rsurface.batchtexcoordlightmap2f = NULL;
9035                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9036                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9037                 rsurface.batchskeletalindex4ub = NULL;
9038                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9039                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9040                 rsurface.batchskeletalweight4ub = NULL;
9041                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9042                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9043                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9044                 rsurface.batchelement3i_indexbuffer = NULL;
9045                 rsurface.batchelement3i_bufferoffset = 0;
9046                 rsurface.batchelement3s = NULL;
9047                 rsurface.batchelement3s_indexbuffer = NULL;
9048                 rsurface.batchelement3s_bufferoffset = 0;
9049                 // we'll only be setting up certain arrays as needed
9050                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9051                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9052                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9053                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9054                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9055                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9056                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9057                 {
9058                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9059                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9060                 }
9061                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9062                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9063                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9064                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9065                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9066                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9067                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9068                 {
9069                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9070                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9071                 }
9072                 numvertices = 0;
9073                 numtriangles = 0;
9074                 for (i = 0;i < texturenumsurfaces;i++)
9075                 {
9076                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9077                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9078                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9079                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9080                         // copy only the data requested
9081                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9082                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9083                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9084                         {
9085                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9086                                 {
9087                                         if (rsurface.batchvertex3f)
9088                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9089                                         else
9090                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9091                                 }
9092                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9093                                 {
9094                                         if (rsurface.modelnormal3f)
9095                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9096                                         else
9097                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9098                                 }
9099                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9100                                 {
9101                                         if (rsurface.modelsvector3f)
9102                                         {
9103                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9104                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9105                                         }
9106                                         else
9107                                         {
9108                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9109                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9110                                         }
9111                                 }
9112                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9113                                 {
9114                                         if (rsurface.modellightmapcolor4f)
9115                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9116                                         else
9117                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9118                                 }
9119                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9120                                 {
9121                                         if (rsurface.modeltexcoordtexture2f)
9122                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9123                                         else
9124                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9125                                 }
9126                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9127                                 {
9128                                         if (rsurface.modeltexcoordlightmap2f)
9129                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9130                                         else
9131                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9132                                 }
9133                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9134                                 {
9135                                         if (rsurface.modelskeletalindex4ub)
9136                                         {
9137                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9138                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9139                                         }
9140                                         else
9141                                         {
9142                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9143                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9144                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9145                                                 for (j = 0;j < surfacenumvertices;j++)
9146                                                         ub[j*4] = 255;
9147                                         }
9148                                 }
9149                         }
9150                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9151                         numvertices += surfacenumvertices;
9152                         numtriangles += surfacenumtriangles;
9153                 }
9154
9155                 // generate a 16bit index array as well if possible
9156                 // (in general, dynamic batches fit)
9157                 if (numvertices <= 65536)
9158                 {
9159                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9160                         for (i = 0;i < numtriangles*3;i++)
9161                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9162                 }
9163
9164                 // since we've copied everything, the batch now starts at 0
9165                 rsurface.batchfirstvertex = 0;
9166                 rsurface.batchnumvertices = batchnumvertices;
9167                 rsurface.batchfirsttriangle = 0;
9168                 rsurface.batchnumtriangles = batchnumtriangles;
9169         }
9170
9171         // apply skeletal animation that would have been done in the vertex shader
9172         if (rsurface.batchskeletaltransform3x4)
9173         {
9174                 const unsigned char *si;
9175                 const unsigned char *sw;
9176                 const float *t[4];
9177                 const float *b = rsurface.batchskeletaltransform3x4;
9178                 float *vp, *vs, *vt, *vn;
9179                 float w[4];
9180                 float m[3][4], n[3][4];
9181                 float tp[3], ts[3], tt[3], tn[3];
9182                 si = rsurface.batchskeletalindex4ub;
9183                 sw = rsurface.batchskeletalweight4ub;
9184                 vp = rsurface.batchvertex3f;
9185                 vs = rsurface.batchsvector3f;
9186                 vt = rsurface.batchtvector3f;
9187                 vn = rsurface.batchnormal3f;
9188                 memset(m[0], 0, sizeof(m));
9189                 memset(n[0], 0, sizeof(n));
9190                 for (i = 0;i < batchnumvertices;i++)
9191                 {
9192                         t[0] = b + si[0]*12;
9193                         if (sw[0] == 255)
9194                         {
9195                                 // common case - only one matrix
9196                                 m[0][0] = t[0][ 0];
9197                                 m[0][1] = t[0][ 1];
9198                                 m[0][2] = t[0][ 2];
9199                                 m[0][3] = t[0][ 3];
9200                                 m[1][0] = t[0][ 4];
9201                                 m[1][1] = t[0][ 5];
9202                                 m[1][2] = t[0][ 6];
9203                                 m[1][3] = t[0][ 7];
9204                                 m[2][0] = t[0][ 8];
9205                                 m[2][1] = t[0][ 9];
9206                                 m[2][2] = t[0][10];
9207                                 m[2][3] = t[0][11];
9208                         }
9209                         else if (sw[2] + sw[3])
9210                         {
9211                                 // blend 4 matrices
9212                                 t[1] = b + si[1]*12;
9213                                 t[2] = b + si[2]*12;
9214                                 t[3] = b + si[3]*12;
9215                                 w[0] = sw[0] * (1.0f / 255.0f);
9216                                 w[1] = sw[1] * (1.0f / 255.0f);
9217                                 w[2] = sw[2] * (1.0f / 255.0f);
9218                                 w[3] = sw[3] * (1.0f / 255.0f);
9219                                 // blend the matrices
9220                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9221                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9222                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9223                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9224                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9225                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9226                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9227                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9228                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9229                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9230                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9231                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9232                         }
9233                         else
9234                         {
9235                                 // blend 2 matrices
9236                                 t[1] = b + si[1]*12;
9237                                 w[0] = sw[0] * (1.0f / 255.0f);
9238                                 w[1] = sw[1] * (1.0f / 255.0f);
9239                                 // blend the matrices
9240                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9241                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9242                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9243                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9244                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9245                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9246                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9247                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9248                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9249                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9250                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9251                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9252                         }
9253                         si += 4;
9254                         sw += 4;
9255                         // modify the vertex
9256                         VectorCopy(vp, tp);
9257                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9258                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9259                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9260                         vp += 3;
9261                         if (vn)
9262                         {
9263                                 // the normal transformation matrix is a set of cross products...
9264                                 CrossProduct(m[1], m[2], n[0]);
9265                                 CrossProduct(m[2], m[0], n[1]);
9266                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9267                                 VectorCopy(vn, tn);
9268                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9269                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9270                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9271                                 VectorNormalize(vn);
9272                                 vn += 3;
9273                                 if (vs)
9274                                 {
9275                                         VectorCopy(vs, ts);
9276                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9277                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9278                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9279                                         VectorNormalize(vs);
9280                                         vs += 3;
9281                                         VectorCopy(vt, tt);
9282                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9283                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9284                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9285                                         VectorNormalize(vt);
9286                                         vt += 3;
9287                                 }
9288                         }
9289                 }
9290                 rsurface.batchskeletaltransform3x4 = NULL;
9291                 rsurface.batchskeletalnumtransforms = 0;
9292         }
9293
9294         // q1bsp surfaces rendered in vertex color mode have to have colors
9295         // calculated based on lightstyles
9296         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9297         {
9298                 // generate color arrays for the surfaces in this list
9299                 int c[4];
9300                 int scale;
9301                 int size3;
9302                 const int *offsets;
9303                 const unsigned char *lm;
9304                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9305                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9306                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9307                 numvertices = 0;
9308                 for (i = 0;i < texturenumsurfaces;i++)
9309                 {
9310                         surface = texturesurfacelist[i];
9311                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9312                         surfacenumvertices = surface->num_vertices;
9313                         if (surface->lightmapinfo->samples)
9314                         {
9315                                 for (j = 0;j < surfacenumvertices;j++)
9316                                 {
9317                                         lm = surface->lightmapinfo->samples + offsets[j];
9318                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9319                                         VectorScale(lm, scale, c);
9320                                         if (surface->lightmapinfo->styles[1] != 255)
9321                                         {
9322                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9323                                                 lm += size3;
9324                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9325                                                 VectorMA(c, scale, lm, c);
9326                                                 if (surface->lightmapinfo->styles[2] != 255)
9327                                                 {
9328                                                         lm += size3;
9329                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9330                                                         VectorMA(c, scale, lm, c);
9331                                                         if (surface->lightmapinfo->styles[3] != 255)
9332                                                         {
9333                                                                 lm += size3;
9334                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9335                                                                 VectorMA(c, scale, lm, c);
9336                                                         }
9337                                                 }
9338                                         }
9339                                         c[0] >>= 7;
9340                                         c[1] >>= 7;
9341                                         c[2] >>= 7;
9342                                         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);
9343                                         numvertices++;
9344                                 }
9345                         }
9346                         else
9347                         {
9348                                 for (j = 0;j < surfacenumvertices;j++)
9349                                 {
9350                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9351                                         numvertices++;
9352                                 }
9353                         }
9354                 }
9355         }
9356
9357         // if vertices are deformed (sprite flares and things in maps, possibly
9358         // water waves, bulges and other deformations), modify the copied vertices
9359         // in place
9360         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9361         {
9362                 switch (deform->deform)
9363                 {
9364                 default:
9365                 case Q3DEFORM_PROJECTIONSHADOW:
9366                 case Q3DEFORM_TEXT0:
9367                 case Q3DEFORM_TEXT1:
9368                 case Q3DEFORM_TEXT2:
9369                 case Q3DEFORM_TEXT3:
9370                 case Q3DEFORM_TEXT4:
9371                 case Q3DEFORM_TEXT5:
9372                 case Q3DEFORM_TEXT6:
9373                 case Q3DEFORM_TEXT7:
9374                 case Q3DEFORM_NONE:
9375                         break;
9376                 case Q3DEFORM_AUTOSPRITE:
9377                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9378                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9379                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9380                         VectorNormalize(newforward);
9381                         VectorNormalize(newright);
9382                         VectorNormalize(newup);
9383 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9384 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9385 //                      rsurface.batchvertex3f_bufferoffset = 0;
9386 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9387 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9388 //                      rsurface.batchsvector3f_bufferoffset = 0;
9389 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9390 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9391 //                      rsurface.batchtvector3f_bufferoffset = 0;
9392 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9393 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9394 //                      rsurface.batchnormal3f_bufferoffset = 0;
9395                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9396                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9397                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9398                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9399                                 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);
9400                         // a single autosprite surface can contain multiple sprites...
9401                         for (j = 0;j < batchnumvertices - 3;j += 4)
9402                         {
9403                                 VectorClear(center);
9404                                 for (i = 0;i < 4;i++)
9405                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9406                                 VectorScale(center, 0.25f, center);
9407                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9408                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9409                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9410                                 for (i = 0;i < 4;i++)
9411                                 {
9412                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9413                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9414                                 }
9415                         }
9416                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9417                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9418                         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);
9419                         break;
9420                 case Q3DEFORM_AUTOSPRITE2:
9421                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9422                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9423                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9424                         VectorNormalize(newforward);
9425                         VectorNormalize(newright);
9426                         VectorNormalize(newup);
9427 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9428 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9429 //                      rsurface.batchvertex3f_bufferoffset = 0;
9430                         {
9431                                 const float *v1, *v2;
9432                                 vec3_t start, end;
9433                                 float f, l;
9434                                 struct
9435                                 {
9436                                         float length2;
9437                                         const float *v1;
9438                                         const float *v2;
9439                                 }
9440                                 shortest[2];
9441                                 memset(shortest, 0, sizeof(shortest));
9442                                 // a single autosprite surface can contain multiple sprites...
9443                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9444                                 {
9445                                         VectorClear(center);
9446                                         for (i = 0;i < 4;i++)
9447                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9448                                         VectorScale(center, 0.25f, center);
9449                                         // find the two shortest edges, then use them to define the
9450                                         // axis vectors for rotating around the central axis
9451                                         for (i = 0;i < 6;i++)
9452                                         {
9453                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9454                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9455                                                 l = VectorDistance2(v1, v2);
9456                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9457                                                 if (v1[2] != v2[2])
9458                                                         l += (1.0f / 1024.0f);
9459                                                 if (shortest[0].length2 > l || i == 0)
9460                                                 {
9461                                                         shortest[1] = shortest[0];
9462                                                         shortest[0].length2 = l;
9463                                                         shortest[0].v1 = v1;
9464                                                         shortest[0].v2 = v2;
9465                                                 }
9466                                                 else if (shortest[1].length2 > l || i == 1)
9467                                                 {
9468                                                         shortest[1].length2 = l;
9469                                                         shortest[1].v1 = v1;
9470                                                         shortest[1].v2 = v2;
9471                                                 }
9472                                         }
9473                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9474                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9475                                         // this calculates the right vector from the shortest edge
9476                                         // and the up vector from the edge midpoints
9477                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9478                                         VectorNormalize(right);
9479                                         VectorSubtract(end, start, up);
9480                                         VectorNormalize(up);
9481                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9482                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9483                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9484                                         VectorNegate(forward, forward);
9485                                         VectorReflect(forward, 0, up, forward);
9486                                         VectorNormalize(forward);
9487                                         CrossProduct(up, forward, newright);
9488                                         VectorNormalize(newright);
9489                                         // rotate the quad around the up axis vector, this is made
9490                                         // especially easy by the fact we know the quad is flat,
9491                                         // so we only have to subtract the center position and
9492                                         // measure distance along the right vector, and then
9493                                         // multiply that by the newright vector and add back the
9494                                         // center position
9495                                         // we also need to subtract the old position to undo the
9496                                         // displacement from the center, which we do with a
9497                                         // DotProduct, the subtraction/addition of center is also
9498                                         // optimized into DotProducts here
9499                                         l = DotProduct(right, center);
9500                                         for (i = 0;i < 4;i++)
9501                                         {
9502                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9503                                                 f = DotProduct(right, v1) - l;
9504                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9505                                         }
9506                                 }
9507                         }
9508                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9509                         {
9510 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9511 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9512 //                              rsurface.batchnormal3f_bufferoffset = 0;
9513                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9514                         }
9515                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9516                         {
9517 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9518 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9519 //                              rsurface.batchsvector3f_bufferoffset = 0;
9520 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9521 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9522 //                              rsurface.batchtvector3f_bufferoffset = 0;
9523                                 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);
9524                         }
9525                         break;
9526                 case Q3DEFORM_NORMAL:
9527                         // deform the normals to make reflections wavey
9528                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9529                         rsurface.batchnormal3f_vertexbuffer = NULL;
9530                         rsurface.batchnormal3f_bufferoffset = 0;
9531                         for (j = 0;j < batchnumvertices;j++)
9532                         {
9533                                 float vertex[3];
9534                                 float *normal = rsurface.batchnormal3f + 3*j;
9535                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9536                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9537                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9538                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9539                                 VectorNormalize(normal);
9540                         }
9541                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9542                         {
9543 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9544 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9545 //                              rsurface.batchsvector3f_bufferoffset = 0;
9546 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9547 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9548 //                              rsurface.batchtvector3f_bufferoffset = 0;
9549                                 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);
9550                         }
9551                         break;
9552                 case Q3DEFORM_WAVE:
9553                         // deform vertex array to make wavey water and flags and such
9554                         waveparms[0] = deform->waveparms[0];
9555                         waveparms[1] = deform->waveparms[1];
9556                         waveparms[2] = deform->waveparms[2];
9557                         waveparms[3] = deform->waveparms[3];
9558                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9559                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9560                         // this is how a divisor of vertex influence on deformation
9561                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9562                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9563 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9564 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9565 //                      rsurface.batchvertex3f_bufferoffset = 0;
9566 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9567 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9568 //                      rsurface.batchnormal3f_bufferoffset = 0;
9569                         for (j = 0;j < batchnumvertices;j++)
9570                         {
9571                                 // if the wavefunc depends on time, evaluate it per-vertex
9572                                 if (waveparms[3])
9573                                 {
9574                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9575                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9576                                 }
9577                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9578                         }
9579                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9580                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9581                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9582                         {
9583 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9584 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9585 //                              rsurface.batchsvector3f_bufferoffset = 0;
9586 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9587 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9588 //                              rsurface.batchtvector3f_bufferoffset = 0;
9589                                 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);
9590                         }
9591                         break;
9592                 case Q3DEFORM_BULGE:
9593                         // deform vertex array to make the surface have moving bulges
9594 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9595 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9596 //                      rsurface.batchvertex3f_bufferoffset = 0;
9597 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9598 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9599 //                      rsurface.batchnormal3f_bufferoffset = 0;
9600                         for (j = 0;j < batchnumvertices;j++)
9601                         {
9602                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9603                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9604                         }
9605                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9606                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9607                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9608                         {
9609 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9610 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9611 //                              rsurface.batchsvector3f_bufferoffset = 0;
9612 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9613 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9614 //                              rsurface.batchtvector3f_bufferoffset = 0;
9615                                 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);
9616                         }
9617                         break;
9618                 case Q3DEFORM_MOVE:
9619                         // deform vertex array
9620                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9621                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9622                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9623                         VectorScale(deform->parms, scale, waveparms);
9624 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9625 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9626 //                      rsurface.batchvertex3f_bufferoffset = 0;
9627                         for (j = 0;j < batchnumvertices;j++)
9628                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9629                         break;
9630                 }
9631         }
9632
9633         // generate texcoords based on the chosen texcoord source
9634         switch(rsurface.texture->tcgen.tcgen)
9635         {
9636         default:
9637         case Q3TCGEN_TEXTURE:
9638                 break;
9639         case Q3TCGEN_LIGHTMAP:
9640 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9641 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9642 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9643                 if (rsurface.batchtexcoordlightmap2f)
9644                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9645                 break;
9646         case Q3TCGEN_VECTOR:
9647 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9648 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9649 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9650                 for (j = 0;j < batchnumvertices;j++)
9651                 {
9652                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9653                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9654                 }
9655                 break;
9656         case Q3TCGEN_ENVIRONMENT:
9657                 // make environment reflections using a spheremap
9658                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9659                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9660                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9661                 for (j = 0;j < batchnumvertices;j++)
9662                 {
9663                         // identical to Q3A's method, but executed in worldspace so
9664                         // carried models can be shiny too
9665
9666                         float viewer[3], d, reflected[3], worldreflected[3];
9667
9668                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9669                         // VectorNormalize(viewer);
9670
9671                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9672
9673                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9674                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9675                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9676                         // note: this is proportinal to viewer, so we can normalize later
9677
9678                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9679                         VectorNormalize(worldreflected);
9680
9681                         // note: this sphere map only uses world x and z!
9682                         // so positive and negative y will LOOK THE SAME.
9683                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9684                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9685                 }
9686                 break;
9687         }
9688         // the only tcmod that needs software vertex processing is turbulent, so
9689         // check for it here and apply the changes if needed
9690         // and we only support that as the first one
9691         // (handling a mixture of turbulent and other tcmods would be problematic
9692         //  without punting it entirely to a software path)
9693         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9694         {
9695                 amplitude = rsurface.texture->tcmods[0].parms[1];
9696                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9697 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9698 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9699 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9700                 for (j = 0;j < batchnumvertices;j++)
9701                 {
9702                         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);
9703                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9704                 }
9705         }
9706
9707         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9708         {
9709                 // convert the modified arrays to vertex structs
9710 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9711 //              rsurface.batchvertexmeshbuffer = NULL;
9712                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9713                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9714                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9715                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9716                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9717                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9718                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9719                 {
9720                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9721                         {
9722                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9723                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9724                         }
9725                 }
9726                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9727                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9728                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9729                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9730                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9731                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9732                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9733                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9734                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9735                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9736                 {
9737                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9738                         {
9739                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9740                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9741                         }
9742                 }
9743         }
9744 }
9745
9746 void RSurf_DrawBatch(void)
9747 {
9748         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9749         // through the pipeline, killing it earlier in the pipeline would have
9750         // per-surface overhead rather than per-batch overhead, so it's best to
9751         // reject it here, before it hits glDraw.
9752         if (rsurface.batchnumtriangles == 0)
9753                 return;
9754 #if 0
9755         // batch debugging code
9756         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9757         {
9758                 int i;
9759                 int j;
9760                 int c;
9761                 const int *e;
9762                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9763                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9764                 {
9765                         c = e[i];
9766                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9767                         {
9768                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9769                                 {
9770                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9771                                                 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);
9772                                         break;
9773                                 }
9774                         }
9775                 }
9776         }
9777 #endif
9778         if (rsurface.batchmultidraw)
9779         {
9780                 // issue multiple draws rather than copying index data
9781                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
9782                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
9783                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
9784                 for (i = 0;i < numsurfaces;)
9785                 {
9786                         // combine consecutive surfaces as one draw
9787                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
9788                                 if (surfacelist[j] != surfacelist[k] + 1)
9789                                         break;
9790                         firstvertex = surfacelist[i]->num_firstvertex;
9791                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
9792                         firsttriangle = surfacelist[i]->num_firsttriangle;
9793                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
9794                         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);
9795                         i = j;
9796                 }
9797         }
9798         else
9799         {
9800                 // there is only one consecutive run of index data (may have been combined)
9801                 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);
9802         }
9803 }
9804
9805 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9806 {
9807         // pick the closest matching water plane
9808         int planeindex, vertexindex, bestplaneindex = -1;
9809         float d, bestd;
9810         vec3_t vert;
9811         const float *v;
9812         r_waterstate_waterplane_t *p;
9813         qboolean prepared = false;
9814         bestd = 0;
9815         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9816         {
9817                 if(p->camera_entity != rsurface.texture->camera_entity)
9818                         continue;
9819                 d = 0;
9820                 if(!prepared)
9821                 {
9822                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
9823                         prepared = true;
9824                         if(rsurface.batchnumvertices == 0)
9825                                 break;
9826                 }
9827                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9828                 {
9829                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9830                         d += fabs(PlaneDiff(vert, &p->plane));
9831                 }
9832                 if (bestd > d || bestplaneindex < 0)
9833                 {
9834                         bestd = d;
9835                         bestplaneindex = planeindex;
9836                 }
9837         }
9838         return bestplaneindex;
9839         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9840         // this situation though, as it might be better to render single larger
9841         // batches with useless stuff (backface culled for example) than to
9842         // render multiple smaller batches
9843 }
9844
9845 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9846 {
9847         int i;
9848         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9849         rsurface.passcolor4f_vertexbuffer = 0;
9850         rsurface.passcolor4f_bufferoffset = 0;
9851         for (i = 0;i < rsurface.batchnumvertices;i++)
9852                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9853 }
9854
9855 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9856 {
9857         int i;
9858         float f;
9859         const float *v;
9860         const float *c;
9861         float *c2;
9862         if (rsurface.passcolor4f)
9863         {
9864                 // generate color arrays
9865                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9866                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9867                 rsurface.passcolor4f_vertexbuffer = 0;
9868                 rsurface.passcolor4f_bufferoffset = 0;
9869                 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)
9870                 {
9871                         f = RSurf_FogVertex(v);
9872                         c2[0] = c[0] * f;
9873                         c2[1] = c[1] * f;
9874                         c2[2] = c[2] * f;
9875                         c2[3] = c[3];
9876                 }
9877         }
9878         else
9879         {
9880                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9881                 rsurface.passcolor4f_vertexbuffer = 0;
9882                 rsurface.passcolor4f_bufferoffset = 0;
9883                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9884                 {
9885                         f = RSurf_FogVertex(v);
9886                         c2[0] = f;
9887                         c2[1] = f;
9888                         c2[2] = f;
9889                         c2[3] = 1;
9890                 }
9891         }
9892 }
9893
9894 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9895 {
9896         int i;
9897         float f;
9898         const float *v;
9899         const float *c;
9900         float *c2;
9901         if (!rsurface.passcolor4f)
9902                 return;
9903         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9904         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9905         rsurface.passcolor4f_vertexbuffer = 0;
9906         rsurface.passcolor4f_bufferoffset = 0;
9907         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)
9908         {
9909                 f = RSurf_FogVertex(v);
9910                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9911                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9912                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9913                 c2[3] = c[3];
9914         }
9915 }
9916
9917 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9918 {
9919         int i;
9920         const float *c;
9921         float *c2;
9922         if (!rsurface.passcolor4f)
9923                 return;
9924         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9925         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9926         rsurface.passcolor4f_vertexbuffer = 0;
9927         rsurface.passcolor4f_bufferoffset = 0;
9928         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9929         {
9930                 c2[0] = c[0] * r;
9931                 c2[1] = c[1] * g;
9932                 c2[2] = c[2] * b;
9933                 c2[3] = c[3] * a;
9934         }
9935 }
9936
9937 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9938 {
9939         int i;
9940         const float *c;
9941         float *c2;
9942         if (!rsurface.passcolor4f)
9943                 return;
9944         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9945         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9946         rsurface.passcolor4f_vertexbuffer = 0;
9947         rsurface.passcolor4f_bufferoffset = 0;
9948         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9949         {
9950                 c2[0] = c[0] + r_refdef.scene.ambient;
9951                 c2[1] = c[1] + r_refdef.scene.ambient;
9952                 c2[2] = c[2] + r_refdef.scene.ambient;
9953                 c2[3] = c[3];
9954         }
9955 }
9956
9957 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9958 {
9959         // TODO: optimize
9960         rsurface.passcolor4f = NULL;
9961         rsurface.passcolor4f_vertexbuffer = 0;
9962         rsurface.passcolor4f_bufferoffset = 0;
9963         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9964         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9965         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9966         GL_Color(r, g, b, a);
9967         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9968         RSurf_DrawBatch();
9969 }
9970
9971 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9972 {
9973         // TODO: optimize applyfog && applycolor case
9974         // just apply fog if necessary, and tint the fog color array if necessary
9975         rsurface.passcolor4f = NULL;
9976         rsurface.passcolor4f_vertexbuffer = 0;
9977         rsurface.passcolor4f_bufferoffset = 0;
9978         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9979         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9980         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9981         GL_Color(r, g, b, a);
9982         RSurf_DrawBatch();
9983 }
9984
9985 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9986 {
9987         // TODO: optimize
9988         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9989         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9990         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9991         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9992         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9993         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9994         GL_Color(r, g, b, a);
9995         RSurf_DrawBatch();
9996 }
9997
9998 static void RSurf_DrawBatch_GL11_ClampColor(void)
9999 {
10000         int i;
10001         const float *c1;
10002         float *c2;
10003         if (!rsurface.passcolor4f)
10004                 return;
10005         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10006         {
10007                 c2[0] = bound(0.0f, c1[0], 1.0f);
10008                 c2[1] = bound(0.0f, c1[1], 1.0f);
10009                 c2[2] = bound(0.0f, c1[2], 1.0f);
10010                 c2[3] = bound(0.0f, c1[3], 1.0f);
10011         }
10012 }
10013
10014 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10015 {
10016         int i;
10017         float f;
10018         const float *v;
10019         const float *n;
10020         float *c;
10021         //vec3_t eyedir;
10022
10023         // fake shading
10024         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10025         rsurface.passcolor4f_vertexbuffer = 0;
10026         rsurface.passcolor4f_bufferoffset = 0;
10027         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)
10028         {
10029                 f = -DotProduct(r_refdef.view.forward, n);
10030                 f = max(0, f);
10031                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10032                 f *= r_refdef.lightmapintensity;
10033                 Vector4Set(c, f, f, f, 1);
10034         }
10035 }
10036
10037 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10038 {
10039         RSurf_DrawBatch_GL11_ApplyFakeLight();
10040         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10041         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10042         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10043         GL_Color(r, g, b, a);
10044         RSurf_DrawBatch();
10045 }
10046
10047 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10048 {
10049         int i;
10050         float f;
10051         float alpha;
10052         const float *v;
10053         const float *n;
10054         float *c;
10055         vec3_t ambientcolor;
10056         vec3_t diffusecolor;
10057         vec3_t lightdir;
10058         // TODO: optimize
10059         // model lighting
10060         VectorCopy(rsurface.modellight_lightdir, lightdir);
10061         f = 0.5f * r_refdef.lightmapintensity;
10062         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10063         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10064         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10065         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10066         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10067         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10068         alpha = *a;
10069         if (VectorLength2(diffusecolor) > 0)
10070         {
10071                 // q3-style directional shading
10072                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10073                 rsurface.passcolor4f_vertexbuffer = 0;
10074                 rsurface.passcolor4f_bufferoffset = 0;
10075                 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)
10076                 {
10077                         if ((f = DotProduct(n, lightdir)) > 0)
10078                                 VectorMA(ambientcolor, f, diffusecolor, c);
10079                         else
10080                                 VectorCopy(ambientcolor, c);
10081                         c[3] = alpha;
10082                 }
10083                 *r = 1;
10084                 *g = 1;
10085                 *b = 1;
10086                 *a = 1;
10087                 *applycolor = false;
10088         }
10089         else
10090         {
10091                 *r = ambientcolor[0];
10092                 *g = ambientcolor[1];
10093                 *b = ambientcolor[2];
10094                 rsurface.passcolor4f = NULL;
10095                 rsurface.passcolor4f_vertexbuffer = 0;
10096                 rsurface.passcolor4f_bufferoffset = 0;
10097         }
10098 }
10099
10100 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10101 {
10102         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10103         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10104         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10105         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10106         GL_Color(r, g, b, a);
10107         RSurf_DrawBatch();
10108 }
10109
10110 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10111 {
10112         int i;
10113         float f;
10114         const float *v;
10115         float *c;
10116
10117         // fake shading
10118         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10119         rsurface.passcolor4f_vertexbuffer = 0;
10120         rsurface.passcolor4f_bufferoffset = 0;
10121
10122         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10123         {
10124                 f = 1 - RSurf_FogVertex(v);
10125                 c[0] = r;
10126                 c[1] = g;
10127                 c[2] = b;
10128                 c[3] = f * a;
10129         }
10130 }
10131
10132 void RSurf_SetupDepthAndCulling(void)
10133 {
10134         // submodels are biased to avoid z-fighting with world surfaces that they
10135         // may be exactly overlapping (avoids z-fighting artifacts on certain
10136         // doors and things in Quake maps)
10137         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10138         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10139         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10140         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10141 }
10142
10143 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10144 {
10145         // transparent sky would be ridiculous
10146         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10147                 return;
10148         R_SetupShader_Generic_NoTexture(false, false);
10149         skyrenderlater = true;
10150         RSurf_SetupDepthAndCulling();
10151         GL_DepthMask(true);
10152         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10153         // skymasking on them, and Quake3 never did sky masking (unlike
10154         // software Quake and software Quake2), so disable the sky masking
10155         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10156         // and skymasking also looks very bad when noclipping outside the
10157         // level, so don't use it then either.
10158         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10159         {
10160                 R_Mesh_ResetTextureState();
10161                 if (skyrendermasked)
10162                 {
10163                         R_SetupShader_DepthOrShadow(false, false, false);
10164                         // depth-only (masking)
10165                         GL_ColorMask(0,0,0,0);
10166                         // just to make sure that braindead drivers don't draw
10167                         // anything despite that colormask...
10168                         GL_BlendFunc(GL_ZERO, GL_ONE);
10169                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10170                         if (rsurface.batchvertex3fbuffer)
10171                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10172                         else
10173                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10174                 }
10175                 else
10176                 {
10177                         R_SetupShader_Generic_NoTexture(false, false);
10178                         // fog sky
10179                         GL_BlendFunc(GL_ONE, GL_ZERO);
10180                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10181                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10182                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10183                 }
10184                 RSurf_DrawBatch();
10185                 if (skyrendermasked)
10186                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10187         }
10188         R_Mesh_ResetTextureState();
10189         GL_Color(1, 1, 1, 1);
10190 }
10191
10192 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10193 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10194 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10195 {
10196         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10197                 return;
10198         if (prepass)
10199         {
10200                 // render screenspace normalmap to texture
10201                 GL_DepthMask(true);
10202                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10203                 RSurf_DrawBatch();
10204                 return;
10205         }
10206
10207         // bind lightmap texture
10208
10209         // water/refraction/reflection/camera surfaces have to be handled specially
10210         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10211         {
10212                 int start, end, startplaneindex;
10213                 for (start = 0;start < texturenumsurfaces;start = end)
10214                 {
10215                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10216                         if(startplaneindex < 0)
10217                         {
10218                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10219                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10220                                 end = start + 1;
10221                                 continue;
10222                         }
10223                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10224                                 ;
10225                         // now that we have a batch using the same planeindex, render it
10226                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10227                         {
10228                                 // render water or distortion background
10229                                 GL_DepthMask(true);
10230                                 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);
10231                                 RSurf_DrawBatch();
10232                                 // blend surface on top
10233                                 GL_DepthMask(false);
10234                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10235                                 RSurf_DrawBatch();
10236                         }
10237                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10238                         {
10239                                 // render surface with reflection texture as input
10240                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10241                                 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);
10242                                 RSurf_DrawBatch();
10243                         }
10244                 }
10245                 return;
10246         }
10247
10248         // render surface batch normally
10249         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10250         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);
10251         RSurf_DrawBatch();
10252 }
10253
10254 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10255 {
10256         // OpenGL 1.3 path - anything not completely ancient
10257         qboolean applycolor;
10258         qboolean applyfog;
10259         int layerindex;
10260         const texturelayer_t *layer;
10261         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);
10262         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10263
10264         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10265         {
10266                 vec4_t layercolor;
10267                 int layertexrgbscale;
10268                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10269                 {
10270                         if (layerindex == 0)
10271                                 GL_AlphaTest(true);
10272                         else
10273                         {
10274                                 GL_AlphaTest(false);
10275                                 GL_DepthFunc(GL_EQUAL);
10276                         }
10277                 }
10278                 GL_DepthMask(layer->depthmask && writedepth);
10279                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10280                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10281                 {
10282                         layertexrgbscale = 4;
10283                         VectorScale(layer->color, 0.25f, layercolor);
10284                 }
10285                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10286                 {
10287                         layertexrgbscale = 2;
10288                         VectorScale(layer->color, 0.5f, layercolor);
10289                 }
10290                 else
10291                 {
10292                         layertexrgbscale = 1;
10293                         VectorScale(layer->color, 1.0f, layercolor);
10294                 }
10295                 layercolor[3] = layer->color[3];
10296                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10297                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10298                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10299                 switch (layer->type)
10300                 {
10301                 case TEXTURELAYERTYPE_LITTEXTURE:
10302                         // single-pass lightmapped texture with 2x rgbscale
10303                         R_Mesh_TexBind(0, r_texture_white);
10304                         R_Mesh_TexMatrix(0, NULL);
10305                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10306                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10307                         R_Mesh_TexBind(1, layer->texture);
10308                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10309                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10310                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10311                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10312                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10313                         else if (FAKELIGHT_ENABLED)
10314                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10315                         else if (rsurface.uselightmaptexture)
10316                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10317                         else
10318                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10319                         break;
10320                 case TEXTURELAYERTYPE_TEXTURE:
10321                         // singletexture unlit texture with transparency support
10322                         R_Mesh_TexBind(0, layer->texture);
10323                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10324                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10325                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10326                         R_Mesh_TexBind(1, 0);
10327                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10328                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10329                         break;
10330                 case TEXTURELAYERTYPE_FOG:
10331                         // singletexture fogging
10332                         if (layer->texture)
10333                         {
10334                                 R_Mesh_TexBind(0, layer->texture);
10335                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10336                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10337                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10338                         }
10339                         else
10340                         {
10341                                 R_Mesh_TexBind(0, 0);
10342                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10343                         }
10344                         R_Mesh_TexBind(1, 0);
10345                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10346                         // generate a color array for the fog pass
10347                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10348                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10349                         RSurf_DrawBatch();
10350                         break;
10351                 default:
10352                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10353                 }
10354         }
10355         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10356         {
10357                 GL_DepthFunc(GL_LEQUAL);
10358                 GL_AlphaTest(false);
10359         }
10360 }
10361
10362 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10363 {
10364         // OpenGL 1.1 - crusty old voodoo path
10365         qboolean applyfog;
10366         int layerindex;
10367         const texturelayer_t *layer;
10368         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);
10369         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10370
10371         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10372         {
10373                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10374                 {
10375                         if (layerindex == 0)
10376                                 GL_AlphaTest(true);
10377                         else
10378                         {
10379                                 GL_AlphaTest(false);
10380                                 GL_DepthFunc(GL_EQUAL);
10381                         }
10382                 }
10383                 GL_DepthMask(layer->depthmask && writedepth);
10384                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10385                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10386                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10387                 switch (layer->type)
10388                 {
10389                 case TEXTURELAYERTYPE_LITTEXTURE:
10390                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10391                         {
10392                                 // two-pass lit texture with 2x rgbscale
10393                                 // first the lightmap pass
10394                                 R_Mesh_TexBind(0, r_texture_white);
10395                                 R_Mesh_TexMatrix(0, NULL);
10396                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10397                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10398                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10399                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10400                                 else if (FAKELIGHT_ENABLED)
10401                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10402                                 else if (rsurface.uselightmaptexture)
10403                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10404                                 else
10405                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10406                                 // then apply the texture to it
10407                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10408                                 R_Mesh_TexBind(0, layer->texture);
10409                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10410                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10411                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10412                                 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);
10413                         }
10414                         else
10415                         {
10416                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10417                                 R_Mesh_TexBind(0, layer->texture);
10418                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10419                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10420                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10421                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10422                                         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);
10423                                 else if (FAKELIGHT_ENABLED)
10424                                         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);
10425                                 else
10426                                         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);
10427                         }
10428                         break;
10429                 case TEXTURELAYERTYPE_TEXTURE:
10430                         // singletexture unlit texture with transparency support
10431                         R_Mesh_TexBind(0, layer->texture);
10432                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10433                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10434                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10435                         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);
10436                         break;
10437                 case TEXTURELAYERTYPE_FOG:
10438                         // singletexture fogging
10439                         if (layer->texture)
10440                         {
10441                                 R_Mesh_TexBind(0, layer->texture);
10442                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10443                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10444                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10445                         }
10446                         else
10447                         {
10448                                 R_Mesh_TexBind(0, 0);
10449                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10450                         }
10451                         // generate a color array for the fog pass
10452                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10453                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10454                         RSurf_DrawBatch();
10455                         break;
10456                 default:
10457                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10458                 }
10459         }
10460         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10461         {
10462                 GL_DepthFunc(GL_LEQUAL);
10463                 GL_AlphaTest(false);
10464         }
10465 }
10466
10467 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10468 {
10469         int vi;
10470         int j;
10471         r_vertexgeneric_t *batchvertex;
10472         float c[4];
10473
10474 //      R_Mesh_ResetTextureState();
10475         R_SetupShader_Generic_NoTexture(false, false);
10476
10477         if(rsurface.texture && rsurface.texture->currentskinframe)
10478         {
10479                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10480                 c[3] *= rsurface.texture->currentalpha;
10481         }
10482         else
10483         {
10484                 c[0] = 1;
10485                 c[1] = 0;
10486                 c[2] = 1;
10487                 c[3] = 1;
10488         }
10489
10490         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10491         {
10492                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10493                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10494                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10495         }
10496
10497         // brighten it up (as texture value 127 means "unlit")
10498         c[0] *= 2 * r_refdef.view.colorscale;
10499         c[1] *= 2 * r_refdef.view.colorscale;
10500         c[2] *= 2 * r_refdef.view.colorscale;
10501
10502         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10503                 c[3] *= r_wateralpha.value;
10504
10505         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10506         {
10507                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10508                 GL_DepthMask(false);
10509         }
10510         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10511         {
10512                 GL_BlendFunc(GL_ONE, GL_ONE);
10513                 GL_DepthMask(false);
10514         }
10515         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10516         {
10517                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10518                 GL_DepthMask(false);
10519         }
10520         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10521         {
10522                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10523                 GL_DepthMask(false);
10524         }
10525         else
10526         {
10527                 GL_BlendFunc(GL_ONE, GL_ZERO);
10528                 GL_DepthMask(writedepth);
10529         }
10530
10531         if (r_showsurfaces.integer == 3)
10532         {
10533                 rsurface.passcolor4f = NULL;
10534
10535                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10536                 {
10537                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10538
10539                         rsurface.passcolor4f = NULL;
10540                         rsurface.passcolor4f_vertexbuffer = 0;
10541                         rsurface.passcolor4f_bufferoffset = 0;
10542                 }
10543                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10544                 {
10545                         qboolean applycolor = true;
10546                         float one = 1.0;
10547
10548                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10549
10550                         r_refdef.lightmapintensity = 1;
10551                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10552                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10553                 }
10554                 else if (FAKELIGHT_ENABLED)
10555                 {
10556                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10557
10558                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10559                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10560                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10561                 }
10562                 else
10563                 {
10564                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10565
10566                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10567                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10568                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10569                 }
10570
10571                 if(!rsurface.passcolor4f)
10572                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10573
10574                 RSurf_DrawBatch_GL11_ApplyAmbient();
10575                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10576                 if(r_refdef.fogenabled)
10577                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10578                 RSurf_DrawBatch_GL11_ClampColor();
10579
10580                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10581                 R_SetupShader_Generic_NoTexture(false, false);
10582                 RSurf_DrawBatch();
10583         }
10584         else if (!r_refdef.view.showdebug)
10585         {
10586                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10587                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10588                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10589                 {
10590                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10591                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10592                 }
10593                 R_Mesh_PrepareVertices_Generic_Unlock();
10594                 RSurf_DrawBatch();
10595         }
10596         else if (r_showsurfaces.integer == 4)
10597         {
10598                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10599                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10600                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10601                 {
10602                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10603                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10604                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10605                 }
10606                 R_Mesh_PrepareVertices_Generic_Unlock();
10607                 RSurf_DrawBatch();
10608         }
10609         else if (r_showsurfaces.integer == 2)
10610         {
10611                 const int *e;
10612                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10613                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10614                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10615                 {
10616                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10617                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10618                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10619                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10620                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10621                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10622                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10623                 }
10624                 R_Mesh_PrepareVertices_Generic_Unlock();
10625                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10626         }
10627         else
10628         {
10629                 int texturesurfaceindex;
10630                 int k;
10631                 const msurface_t *surface;
10632                 float surfacecolor4f[4];
10633                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10634                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10635                 vi = 0;
10636                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10637                 {
10638                         surface = texturesurfacelist[texturesurfaceindex];
10639                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10640                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10641                         for (j = 0;j < surface->num_vertices;j++)
10642                         {
10643                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10644                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10645                                 vi++;
10646                         }
10647                 }
10648                 R_Mesh_PrepareVertices_Generic_Unlock();
10649                 RSurf_DrawBatch();
10650         }
10651 }
10652
10653 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10654 {
10655         CHECKGLERROR
10656         RSurf_SetupDepthAndCulling();
10657         if (r_showsurfaces.integer)
10658         {
10659                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10660                 return;
10661         }
10662         switch (vid.renderpath)
10663         {
10664         case RENDERPATH_GL20:
10665         case RENDERPATH_D3D9:
10666         case RENDERPATH_D3D10:
10667         case RENDERPATH_D3D11:
10668         case RENDERPATH_SOFT:
10669         case RENDERPATH_GLES2:
10670                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10671                 break;
10672         case RENDERPATH_GL13:
10673         case RENDERPATH_GLES1:
10674                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10675                 break;
10676         case RENDERPATH_GL11:
10677                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10678                 break;
10679         }
10680         CHECKGLERROR
10681 }
10682
10683 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10684 {
10685         CHECKGLERROR
10686         RSurf_SetupDepthAndCulling();
10687         if (r_showsurfaces.integer)
10688         {
10689                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10690                 return;
10691         }
10692         switch (vid.renderpath)
10693         {
10694         case RENDERPATH_GL20:
10695         case RENDERPATH_D3D9:
10696         case RENDERPATH_D3D10:
10697         case RENDERPATH_D3D11:
10698         case RENDERPATH_SOFT:
10699         case RENDERPATH_GLES2:
10700                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10701                 break;
10702         case RENDERPATH_GL13:
10703         case RENDERPATH_GLES1:
10704                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10705                 break;
10706         case RENDERPATH_GL11:
10707                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10708                 break;
10709         }
10710         CHECKGLERROR
10711 }
10712
10713 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10714 {
10715         int i, j;
10716         int texturenumsurfaces, endsurface;
10717         texture_t *texture;
10718         const msurface_t *surface;
10719         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10720
10721         // if the model is static it doesn't matter what value we give for
10722         // wantnormals and wanttangents, so this logic uses only rules applicable
10723         // to a model, knowing that they are meaningless otherwise
10724         if (ent == r_refdef.scene.worldentity)
10725                 RSurf_ActiveWorldEntity();
10726         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10727                 RSurf_ActiveModelEntity(ent, false, false, false);
10728         else
10729         {
10730                 switch (vid.renderpath)
10731                 {
10732                 case RENDERPATH_GL20:
10733                 case RENDERPATH_D3D9:
10734                 case RENDERPATH_D3D10:
10735                 case RENDERPATH_D3D11:
10736                 case RENDERPATH_SOFT:
10737                 case RENDERPATH_GLES2:
10738                         RSurf_ActiveModelEntity(ent, true, true, false);
10739                         break;
10740                 case RENDERPATH_GL11:
10741                 case RENDERPATH_GL13:
10742                 case RENDERPATH_GLES1:
10743                         RSurf_ActiveModelEntity(ent, true, false, false);
10744                         break;
10745                 }
10746         }
10747
10748         if (r_transparentdepthmasking.integer)
10749         {
10750                 qboolean setup = false;
10751                 for (i = 0;i < numsurfaces;i = j)
10752                 {
10753                         j = i + 1;
10754                         surface = rsurface.modelsurfaces + surfacelist[i];
10755                         texture = surface->texture;
10756                         rsurface.texture = R_GetCurrentTexture(texture);
10757                         rsurface.lightmaptexture = NULL;
10758                         rsurface.deluxemaptexture = NULL;
10759                         rsurface.uselightmaptexture = false;
10760                         // scan ahead until we find a different texture
10761                         endsurface = min(i + 1024, numsurfaces);
10762                         texturenumsurfaces = 0;
10763                         texturesurfacelist[texturenumsurfaces++] = surface;
10764                         for (;j < endsurface;j++)
10765                         {
10766                                 surface = rsurface.modelsurfaces + surfacelist[j];
10767                                 if (texture != surface->texture)
10768                                         break;
10769                                 texturesurfacelist[texturenumsurfaces++] = surface;
10770                         }
10771                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10772                                 continue;
10773                         // render the range of surfaces as depth
10774                         if (!setup)
10775                         {
10776                                 setup = true;
10777                                 GL_ColorMask(0,0,0,0);
10778                                 GL_Color(1,1,1,1);
10779                                 GL_DepthTest(true);
10780                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10781                                 GL_DepthMask(true);
10782 //                              R_Mesh_ResetTextureState();
10783                         }
10784                         RSurf_SetupDepthAndCulling();
10785                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10786                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
10787                         if (rsurface.batchvertex3fbuffer)
10788                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10789                         else
10790                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10791                         RSurf_DrawBatch();
10792                 }
10793                 if (setup)
10794                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10795         }
10796
10797         for (i = 0;i < numsurfaces;i = j)
10798         {
10799                 j = i + 1;
10800                 surface = rsurface.modelsurfaces + surfacelist[i];
10801                 texture = surface->texture;
10802                 rsurface.texture = R_GetCurrentTexture(texture);
10803                 // scan ahead until we find a different texture
10804                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10805                 texturenumsurfaces = 0;
10806                 texturesurfacelist[texturenumsurfaces++] = surface;
10807                 if(FAKELIGHT_ENABLED)
10808                 {
10809                         rsurface.lightmaptexture = NULL;
10810                         rsurface.deluxemaptexture = NULL;
10811                         rsurface.uselightmaptexture = false;
10812                         for (;j < endsurface;j++)
10813                         {
10814                                 surface = rsurface.modelsurfaces + surfacelist[j];
10815                                 if (texture != surface->texture)
10816                                         break;
10817                                 texturesurfacelist[texturenumsurfaces++] = surface;
10818                         }
10819                 }
10820                 else
10821                 {
10822                         rsurface.lightmaptexture = surface->lightmaptexture;
10823                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10824                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10825                         for (;j < endsurface;j++)
10826                         {
10827                                 surface = rsurface.modelsurfaces + surfacelist[j];
10828                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10829                                         break;
10830                                 texturesurfacelist[texturenumsurfaces++] = surface;
10831                         }
10832                 }
10833                 // render the range of surfaces
10834                 if (ent == r_refdef.scene.worldentity)
10835                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10836                 else
10837                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10838         }
10839         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10840 }
10841
10842 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10843 {
10844         // transparent surfaces get pushed off into the transparent queue
10845         int surfacelistindex;
10846         const msurface_t *surface;
10847         vec3_t tempcenter, center;
10848         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10849         {
10850                 surface = texturesurfacelist[surfacelistindex];
10851                 if (r_transparent_sortsurfacesbynearest.integer)
10852                 {
10853                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10854                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10855                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10856                 }
10857                 else
10858                 {
10859                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10860                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10861                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10862                 }
10863                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10864                 if (rsurface.entity->transparent_offset) // transparent offset
10865                 {
10866                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10867                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10868                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10869                 }
10870                 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);
10871         }
10872 }
10873
10874 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10875 {
10876         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10877                 return;
10878         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10879                 return;
10880         RSurf_SetupDepthAndCulling();
10881         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10882         if (rsurface.batchvertex3fbuffer)
10883                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10884         else
10885                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10886         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
10887         RSurf_DrawBatch();
10888 }
10889
10890 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10891 {
10892         CHECKGLERROR
10893         if (depthonly)
10894                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10895         else if (prepass)
10896         {
10897                 if (!rsurface.texture->currentnumlayers)
10898                         return;
10899                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10900                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10901                 else
10902                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10903         }
10904         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10905                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10906         else if (!rsurface.texture->currentnumlayers)
10907                 return;
10908         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10909         {
10910                 // in the deferred case, transparent surfaces were queued during prepass
10911                 if (!r_shadow_usingdeferredprepass)
10912                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10913         }
10914         else
10915         {
10916                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10917                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10918         }
10919         CHECKGLERROR
10920 }
10921
10922 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10923 {
10924         int i, j;
10925         texture_t *texture;
10926         R_FrameData_SetMark();
10927         // break the surface list down into batches by texture and use of lightmapping
10928         for (i = 0;i < numsurfaces;i = j)
10929         {
10930                 j = i + 1;
10931                 // texture is the base texture pointer, rsurface.texture is the
10932                 // current frame/skin the texture is directing us to use (for example
10933                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10934                 // use skin 1 instead)
10935                 texture = surfacelist[i]->texture;
10936                 rsurface.texture = R_GetCurrentTexture(texture);
10937                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10938                 {
10939                         // if this texture is not the kind we want, skip ahead to the next one
10940                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10941                                 ;
10942                         continue;
10943                 }
10944                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10945                 {
10946                         rsurface.lightmaptexture = NULL;
10947                         rsurface.deluxemaptexture = NULL;
10948                         rsurface.uselightmaptexture = false;
10949                         // simply scan ahead until we find a different texture or lightmap state
10950                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10951                                 ;
10952                 }
10953                 else
10954                 {
10955                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10956                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10957                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10958                         // simply scan ahead until we find a different texture or lightmap state
10959                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10960                                 ;
10961                 }
10962                 // render the range of surfaces
10963                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10964         }
10965         R_FrameData_ReturnToMark();
10966 }
10967
10968 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10969 {
10970         CHECKGLERROR
10971         if (depthonly)
10972                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10973         else if (prepass)
10974         {
10975                 if (!rsurface.texture->currentnumlayers)
10976                         return;
10977                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10978                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10979                 else
10980                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10981         }
10982         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10983                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10984         else if (!rsurface.texture->currentnumlayers)
10985                 return;
10986         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10987         {
10988                 // in the deferred case, transparent surfaces were queued during prepass
10989                 if (!r_shadow_usingdeferredprepass)
10990                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10991         }
10992         else
10993         {
10994                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10995                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10996         }
10997         CHECKGLERROR
10998 }
10999
11000 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11001 {
11002         int i, j;
11003         texture_t *texture;
11004         R_FrameData_SetMark();
11005         // break the surface list down into batches by texture and use of lightmapping
11006         for (i = 0;i < numsurfaces;i = j)
11007         {
11008                 j = i + 1;
11009                 // texture is the base texture pointer, rsurface.texture is the
11010                 // current frame/skin the texture is directing us to use (for example
11011                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11012                 // use skin 1 instead)
11013                 texture = surfacelist[i]->texture;
11014                 rsurface.texture = R_GetCurrentTexture(texture);
11015                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11016                 {
11017                         // if this texture is not the kind we want, skip ahead to the next one
11018                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11019                                 ;
11020                         continue;
11021                 }
11022                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11023                 {
11024                         rsurface.lightmaptexture = NULL;
11025                         rsurface.deluxemaptexture = NULL;
11026                         rsurface.uselightmaptexture = false;
11027                         // simply scan ahead until we find a different texture or lightmap state
11028                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11029                                 ;
11030                 }
11031                 else
11032                 {
11033                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11034                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11035                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11036                         // simply scan ahead until we find a different texture or lightmap state
11037                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11038                                 ;
11039                 }
11040                 // render the range of surfaces
11041                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11042         }
11043         R_FrameData_ReturnToMark();
11044 }
11045
11046 float locboxvertex3f[6*4*3] =
11047 {
11048         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11049         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11050         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11051         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11052         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11053         1,0,0, 0,0,0, 0,1,0, 1,1,0
11054 };
11055
11056 unsigned short locboxelements[6*2*3] =
11057 {
11058          0, 1, 2, 0, 2, 3,
11059          4, 5, 6, 4, 6, 7,
11060          8, 9,10, 8,10,11,
11061         12,13,14, 12,14,15,
11062         16,17,18, 16,18,19,
11063         20,21,22, 20,22,23
11064 };
11065
11066 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11067 {
11068         int i, j;
11069         cl_locnode_t *loc = (cl_locnode_t *)ent;
11070         vec3_t mins, size;
11071         float vertex3f[6*4*3];
11072         CHECKGLERROR
11073         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11074         GL_DepthMask(false);
11075         GL_DepthRange(0, 1);
11076         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11077         GL_DepthTest(true);
11078         GL_CullFace(GL_NONE);
11079         R_EntityMatrix(&identitymatrix);
11080
11081 //      R_Mesh_ResetTextureState();
11082
11083         i = surfacelist[0];
11084         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11085                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11086                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11087                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11088
11089         if (VectorCompare(loc->mins, loc->maxs))
11090         {
11091                 VectorSet(size, 2, 2, 2);
11092                 VectorMA(loc->mins, -0.5f, size, mins);
11093         }
11094         else
11095         {
11096                 VectorCopy(loc->mins, mins);
11097                 VectorSubtract(loc->maxs, loc->mins, size);
11098         }
11099
11100         for (i = 0;i < 6*4*3;)
11101                 for (j = 0;j < 3;j++, i++)
11102                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11103
11104         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11105         R_SetupShader_Generic_NoTexture(false, false);
11106         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11107 }
11108
11109 void R_DrawLocs(void)
11110 {
11111         int index;
11112         cl_locnode_t *loc, *nearestloc;
11113         vec3_t center;
11114         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11115         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11116         {
11117                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11118                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11119         }
11120 }
11121
11122 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11123 {
11124         if (decalsystem->decals)
11125                 Mem_Free(decalsystem->decals);
11126         memset(decalsystem, 0, sizeof(*decalsystem));
11127 }
11128
11129 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)
11130 {
11131         tridecal_t *decal;
11132         tridecal_t *decals;
11133         int i;
11134
11135         // expand or initialize the system
11136         if (decalsystem->maxdecals <= decalsystem->numdecals)
11137         {
11138                 decalsystem_t old = *decalsystem;
11139                 qboolean useshortelements;
11140                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11141                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11142                 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)));
11143                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11144                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11145                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11146                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11147                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11148                 if (decalsystem->numdecals)
11149                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11150                 if (old.decals)
11151                         Mem_Free(old.decals);
11152                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11153                         decalsystem->element3i[i] = i;
11154                 if (useshortelements)
11155                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11156                                 decalsystem->element3s[i] = i;
11157         }
11158
11159         // grab a decal and search for another free slot for the next one
11160         decals = decalsystem->decals;
11161         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11162         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11163                 ;
11164         decalsystem->freedecal = i;
11165         if (decalsystem->numdecals <= i)
11166                 decalsystem->numdecals = i + 1;
11167
11168         // initialize the decal
11169         decal->lived = 0;
11170         decal->triangleindex = triangleindex;
11171         decal->surfaceindex = surfaceindex;
11172         decal->decalsequence = decalsequence;
11173         decal->color4f[0][0] = c0[0];
11174         decal->color4f[0][1] = c0[1];
11175         decal->color4f[0][2] = c0[2];
11176         decal->color4f[0][3] = 1;
11177         decal->color4f[1][0] = c1[0];
11178         decal->color4f[1][1] = c1[1];
11179         decal->color4f[1][2] = c1[2];
11180         decal->color4f[1][3] = 1;
11181         decal->color4f[2][0] = c2[0];
11182         decal->color4f[2][1] = c2[1];
11183         decal->color4f[2][2] = c2[2];
11184         decal->color4f[2][3] = 1;
11185         decal->vertex3f[0][0] = v0[0];
11186         decal->vertex3f[0][1] = v0[1];
11187         decal->vertex3f[0][2] = v0[2];
11188         decal->vertex3f[1][0] = v1[0];
11189         decal->vertex3f[1][1] = v1[1];
11190         decal->vertex3f[1][2] = v1[2];
11191         decal->vertex3f[2][0] = v2[0];
11192         decal->vertex3f[2][1] = v2[1];
11193         decal->vertex3f[2][2] = v2[2];
11194         decal->texcoord2f[0][0] = t0[0];
11195         decal->texcoord2f[0][1] = t0[1];
11196         decal->texcoord2f[1][0] = t1[0];
11197         decal->texcoord2f[1][1] = t1[1];
11198         decal->texcoord2f[2][0] = t2[0];
11199         decal->texcoord2f[2][1] = t2[1];
11200         TriangleNormal(v0, v1, v2, decal->plane);
11201         VectorNormalize(decal->plane);
11202         decal->plane[3] = DotProduct(v0, decal->plane);
11203 }
11204
11205 extern cvar_t cl_decals_bias;
11206 extern cvar_t cl_decals_models;
11207 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11208 // baseparms, parms, temps
11209 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)
11210 {
11211         int cornerindex;
11212         int index;
11213         float v[9][3];
11214         const float *vertex3f;
11215         const float *normal3f;
11216         int numpoints;
11217         float points[2][9][3];
11218         float temp[3];
11219         float tc[9][2];
11220         float f;
11221         float c[9][4];
11222         const int *e;
11223
11224         e = rsurface.modelelement3i + 3*triangleindex;
11225
11226         vertex3f = rsurface.modelvertex3f;
11227         normal3f = rsurface.modelnormal3f;
11228
11229         if (normal3f)
11230         {
11231                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11232                 {
11233                         index = 3*e[cornerindex];
11234                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11235                 }
11236         }
11237         else
11238         {
11239                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11240                 {
11241                         index = 3*e[cornerindex];
11242                         VectorCopy(vertex3f + index, v[cornerindex]);
11243                 }
11244         }
11245
11246         // cull backfaces
11247         //TriangleNormal(v[0], v[1], v[2], normal);
11248         //if (DotProduct(normal, localnormal) < 0.0f)
11249         //      continue;
11250         // clip by each of the box planes formed from the projection matrix
11251         // if anything survives, we emit the decal
11252         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]);
11253         if (numpoints < 3)
11254                 return;
11255         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]);
11256         if (numpoints < 3)
11257                 return;
11258         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]);
11259         if (numpoints < 3)
11260                 return;
11261         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]);
11262         if (numpoints < 3)
11263                 return;
11264         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]);
11265         if (numpoints < 3)
11266                 return;
11267         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]);
11268         if (numpoints < 3)
11269                 return;
11270         // some part of the triangle survived, so we have to accept it...
11271         if (dynamic)
11272         {
11273                 // dynamic always uses the original triangle
11274                 numpoints = 3;
11275                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11276                 {
11277                         index = 3*e[cornerindex];
11278                         VectorCopy(vertex3f + index, v[cornerindex]);
11279                 }
11280         }
11281         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11282         {
11283                 // convert vertex positions to texcoords
11284                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11285                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11286                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11287                 // calculate distance fade from the projection origin
11288                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11289                 f = bound(0.0f, f, 1.0f);
11290                 c[cornerindex][0] = r * f;
11291                 c[cornerindex][1] = g * f;
11292                 c[cornerindex][2] = b * f;
11293                 c[cornerindex][3] = 1.0f;
11294                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11295         }
11296         if (dynamic)
11297                 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);
11298         else
11299                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11300                         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);
11301 }
11302 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)
11303 {
11304         matrix4x4_t projection;
11305         decalsystem_t *decalsystem;
11306         qboolean dynamic;
11307         dp_model_t *model;
11308         const msurface_t *surface;
11309         const msurface_t *surfaces;
11310         const int *surfacelist;
11311         const texture_t *texture;
11312         int numtriangles;
11313         int numsurfacelist;
11314         int surfacelistindex;
11315         int surfaceindex;
11316         int triangleindex;
11317         float localorigin[3];
11318         float localnormal[3];
11319         float localmins[3];
11320         float localmaxs[3];
11321         float localsize;
11322         //float normal[3];
11323         float planes[6][4];
11324         float angles[3];
11325         bih_t *bih;
11326         int bih_triangles_count;
11327         int bih_triangles[256];
11328         int bih_surfaces[256];
11329
11330         decalsystem = &ent->decalsystem;
11331         model = ent->model;
11332         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11333         {
11334                 R_DecalSystem_Reset(&ent->decalsystem);
11335                 return;
11336         }
11337
11338         if (!model->brush.data_leafs && !cl_decals_models.integer)
11339         {
11340                 if (decalsystem->model)
11341                         R_DecalSystem_Reset(decalsystem);
11342                 return;
11343         }
11344
11345         if (decalsystem->model != model)
11346                 R_DecalSystem_Reset(decalsystem);
11347         decalsystem->model = model;
11348
11349         RSurf_ActiveModelEntity(ent, true, false, false);
11350
11351         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11352         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11353         VectorNormalize(localnormal);
11354         localsize = worldsize*rsurface.inversematrixscale;
11355         localmins[0] = localorigin[0] - localsize;
11356         localmins[1] = localorigin[1] - localsize;
11357         localmins[2] = localorigin[2] - localsize;
11358         localmaxs[0] = localorigin[0] + localsize;
11359         localmaxs[1] = localorigin[1] + localsize;
11360         localmaxs[2] = localorigin[2] + localsize;
11361
11362         //VectorCopy(localnormal, planes[4]);
11363         //VectorVectors(planes[4], planes[2], planes[0]);
11364         AnglesFromVectors(angles, localnormal, NULL, false);
11365         AngleVectors(angles, planes[0], planes[2], planes[4]);
11366         VectorNegate(planes[0], planes[1]);
11367         VectorNegate(planes[2], planes[3]);
11368         VectorNegate(planes[4], planes[5]);
11369         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11370         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11371         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11372         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11373         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11374         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11375
11376 #if 1
11377 // works
11378 {
11379         matrix4x4_t forwardprojection;
11380         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11381         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11382 }
11383 #else
11384 // broken
11385 {
11386         float projectionvector[4][3];
11387         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11388         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11389         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11390         projectionvector[0][0] = planes[0][0] * ilocalsize;
11391         projectionvector[0][1] = planes[1][0] * ilocalsize;
11392         projectionvector[0][2] = planes[2][0] * ilocalsize;
11393         projectionvector[1][0] = planes[0][1] * ilocalsize;
11394         projectionvector[1][1] = planes[1][1] * ilocalsize;
11395         projectionvector[1][2] = planes[2][1] * ilocalsize;
11396         projectionvector[2][0] = planes[0][2] * ilocalsize;
11397         projectionvector[2][1] = planes[1][2] * ilocalsize;
11398         projectionvector[2][2] = planes[2][2] * ilocalsize;
11399         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11400         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11401         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11402         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11403 }
11404 #endif
11405
11406         dynamic = model->surfmesh.isanimated;
11407         numsurfacelist = model->nummodelsurfaces;
11408         surfacelist = model->sortedmodelsurfaces;
11409         surfaces = model->data_surfaces;
11410
11411         bih = NULL;
11412         bih_triangles_count = -1;
11413         if(!dynamic)
11414         {
11415                 if(model->render_bih.numleafs)
11416                         bih = &model->render_bih;
11417                 else if(model->collision_bih.numleafs)
11418                         bih = &model->collision_bih;
11419         }
11420         if(bih)
11421                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11422         if(bih_triangles_count == 0)
11423                 return;
11424         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11425                 return;
11426         if(bih_triangles_count > 0)
11427         {
11428                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11429                 {
11430                         surfaceindex = bih_surfaces[triangleindex];
11431                         surface = surfaces + surfaceindex;
11432                         texture = surface->texture;
11433                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11434                                 continue;
11435                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11436                                 continue;
11437                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11438                 }
11439         }
11440         else
11441         {
11442                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11443                 {
11444                         surfaceindex = surfacelist[surfacelistindex];
11445                         surface = surfaces + surfaceindex;
11446                         // check cull box first because it rejects more than any other check
11447                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11448                                 continue;
11449                         // skip transparent surfaces
11450                         texture = surface->texture;
11451                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11452                                 continue;
11453                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11454                                 continue;
11455                         numtriangles = surface->num_triangles;
11456                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11457                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11458                 }
11459         }
11460 }
11461
11462 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11463 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)
11464 {
11465         int renderentityindex;
11466         float worldmins[3];
11467         float worldmaxs[3];
11468         entity_render_t *ent;
11469
11470         if (!cl_decals_newsystem.integer)
11471                 return;
11472
11473         worldmins[0] = worldorigin[0] - worldsize;
11474         worldmins[1] = worldorigin[1] - worldsize;
11475         worldmins[2] = worldorigin[2] - worldsize;
11476         worldmaxs[0] = worldorigin[0] + worldsize;
11477         worldmaxs[1] = worldorigin[1] + worldsize;
11478         worldmaxs[2] = worldorigin[2] + worldsize;
11479
11480         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11481
11482         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11483         {
11484                 ent = r_refdef.scene.entities[renderentityindex];
11485                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11486                         continue;
11487
11488                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11489         }
11490 }
11491
11492 typedef struct r_decalsystem_splatqueue_s
11493 {
11494         vec3_t worldorigin;
11495         vec3_t worldnormal;
11496         float color[4];
11497         float tcrange[4];
11498         float worldsize;
11499         int decalsequence;
11500 }
11501 r_decalsystem_splatqueue_t;
11502
11503 int r_decalsystem_numqueued = 0;
11504 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11505
11506 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)
11507 {
11508         r_decalsystem_splatqueue_t *queue;
11509
11510         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11511                 return;
11512
11513         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11514         VectorCopy(worldorigin, queue->worldorigin);
11515         VectorCopy(worldnormal, queue->worldnormal);
11516         Vector4Set(queue->color, r, g, b, a);
11517         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11518         queue->worldsize = worldsize;
11519         queue->decalsequence = cl.decalsequence++;
11520 }
11521
11522 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11523 {
11524         int i;
11525         r_decalsystem_splatqueue_t *queue;
11526
11527         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11528                 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);
11529         r_decalsystem_numqueued = 0;
11530 }
11531
11532 extern cvar_t cl_decals_max;
11533 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11534 {
11535         int i;
11536         decalsystem_t *decalsystem = &ent->decalsystem;
11537         int numdecals;
11538         int killsequence;
11539         tridecal_t *decal;
11540         float frametime;
11541         float lifetime;
11542
11543         if (!decalsystem->numdecals)
11544                 return;
11545
11546         if (r_showsurfaces.integer)
11547                 return;
11548
11549         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11550         {
11551                 R_DecalSystem_Reset(decalsystem);
11552                 return;
11553         }
11554
11555         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11556         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11557
11558         if (decalsystem->lastupdatetime)
11559                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11560         else
11561                 frametime = 0;
11562         decalsystem->lastupdatetime = r_refdef.scene.time;
11563         numdecals = decalsystem->numdecals;
11564
11565         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11566         {
11567                 if (decal->color4f[0][3])
11568                 {
11569                         decal->lived += frametime;
11570                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11571                         {
11572                                 memset(decal, 0, sizeof(*decal));
11573                                 if (decalsystem->freedecal > i)
11574                                         decalsystem->freedecal = i;
11575                         }
11576                 }
11577         }
11578         decal = decalsystem->decals;
11579         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11580                 numdecals--;
11581
11582         // collapse the array by shuffling the tail decals into the gaps
11583         for (;;)
11584         {
11585                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11586                         decalsystem->freedecal++;
11587                 if (decalsystem->freedecal == numdecals)
11588                         break;
11589                 decal[decalsystem->freedecal] = decal[--numdecals];
11590         }
11591
11592         decalsystem->numdecals = numdecals;
11593
11594         if (numdecals <= 0)
11595         {
11596                 // if there are no decals left, reset decalsystem
11597                 R_DecalSystem_Reset(decalsystem);
11598         }
11599 }
11600
11601 extern skinframe_t *decalskinframe;
11602 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11603 {
11604         int i;
11605         decalsystem_t *decalsystem = &ent->decalsystem;
11606         int numdecals;
11607         tridecal_t *decal;
11608         float faderate;
11609         float alpha;
11610         float *v3f;
11611         float *c4f;
11612         float *t2f;
11613         const int *e;
11614         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11615         int numtris = 0;
11616
11617         numdecals = decalsystem->numdecals;
11618         if (!numdecals)
11619                 return;
11620
11621         if (r_showsurfaces.integer)
11622                 return;
11623
11624         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11625         {
11626                 R_DecalSystem_Reset(decalsystem);
11627                 return;
11628         }
11629
11630         // if the model is static it doesn't matter what value we give for
11631         // wantnormals and wanttangents, so this logic uses only rules applicable
11632         // to a model, knowing that they are meaningless otherwise
11633         if (ent == r_refdef.scene.worldentity)
11634                 RSurf_ActiveWorldEntity();
11635         else
11636                 RSurf_ActiveModelEntity(ent, false, false, false);
11637
11638         decalsystem->lastupdatetime = r_refdef.scene.time;
11639
11640         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11641
11642         // update vertex positions for animated models
11643         v3f = decalsystem->vertex3f;
11644         c4f = decalsystem->color4f;
11645         t2f = decalsystem->texcoord2f;
11646         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11647         {
11648                 if (!decal->color4f[0][3])
11649                         continue;
11650
11651                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11652                         continue;
11653
11654                 // skip backfaces
11655                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11656                         continue;
11657
11658                 // update color values for fading decals
11659                 if (decal->lived >= cl_decals_time.value)
11660                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11661                 else
11662                         alpha = 1.0f;
11663
11664                 c4f[ 0] = decal->color4f[0][0] * alpha;
11665                 c4f[ 1] = decal->color4f[0][1] * alpha;
11666                 c4f[ 2] = decal->color4f[0][2] * alpha;
11667                 c4f[ 3] = 1;
11668                 c4f[ 4] = decal->color4f[1][0] * alpha;
11669                 c4f[ 5] = decal->color4f[1][1] * alpha;
11670                 c4f[ 6] = decal->color4f[1][2] * alpha;
11671                 c4f[ 7] = 1;
11672                 c4f[ 8] = decal->color4f[2][0] * alpha;
11673                 c4f[ 9] = decal->color4f[2][1] * alpha;
11674                 c4f[10] = decal->color4f[2][2] * alpha;
11675                 c4f[11] = 1;
11676
11677                 t2f[0] = decal->texcoord2f[0][0];
11678                 t2f[1] = decal->texcoord2f[0][1];
11679                 t2f[2] = decal->texcoord2f[1][0];
11680                 t2f[3] = decal->texcoord2f[1][1];
11681                 t2f[4] = decal->texcoord2f[2][0];
11682                 t2f[5] = decal->texcoord2f[2][1];
11683
11684                 // update vertex positions for animated models
11685                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11686                 {
11687                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11688                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11689                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11690                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11691                 }
11692                 else
11693                 {
11694                         VectorCopy(decal->vertex3f[0], v3f);
11695                         VectorCopy(decal->vertex3f[1], v3f + 3);
11696                         VectorCopy(decal->vertex3f[2], v3f + 6);
11697                 }
11698
11699                 if (r_refdef.fogenabled)
11700                 {
11701                         alpha = RSurf_FogVertex(v3f);
11702                         VectorScale(c4f, alpha, c4f);
11703                         alpha = RSurf_FogVertex(v3f + 3);
11704                         VectorScale(c4f + 4, alpha, c4f + 4);
11705                         alpha = RSurf_FogVertex(v3f + 6);
11706                         VectorScale(c4f + 8, alpha, c4f + 8);
11707                 }
11708
11709                 v3f += 9;
11710                 c4f += 12;
11711                 t2f += 6;
11712                 numtris++;
11713         }
11714
11715         if (numtris > 0)
11716         {
11717                 r_refdef.stats.drawndecals += numtris;
11718
11719                 // now render the decals all at once
11720                 // (this assumes they all use one particle font texture!)
11721                 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);
11722 //              R_Mesh_ResetTextureState();
11723                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11724                 GL_DepthMask(false);
11725                 GL_DepthRange(0, 1);
11726                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11727                 GL_DepthTest(true);
11728                 GL_CullFace(GL_NONE);
11729                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11730                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11731                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11732         }
11733 }
11734
11735 static void R_DrawModelDecals(void)
11736 {
11737         int i, numdecals;
11738
11739         // fade faster when there are too many decals
11740         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11741         for (i = 0;i < r_refdef.scene.numentities;i++)
11742                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11743
11744         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11745         for (i = 0;i < r_refdef.scene.numentities;i++)
11746                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11747                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11748
11749         R_DecalSystem_ApplySplatEntitiesQueue();
11750
11751         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11752         for (i = 0;i < r_refdef.scene.numentities;i++)
11753                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11754
11755         r_refdef.stats.totaldecals += numdecals;
11756
11757         if (r_showsurfaces.integer)
11758                 return;
11759
11760         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11761
11762         for (i = 0;i < r_refdef.scene.numentities;i++)
11763         {
11764                 if (!r_refdef.viewcache.entityvisible[i])
11765                         continue;
11766                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11767                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11768         }
11769 }
11770
11771 extern cvar_t mod_collision_bih;
11772 static void R_DrawDebugModel(void)
11773 {
11774         entity_render_t *ent = rsurface.entity;
11775         int i, j, k, l, flagsmask;
11776         const msurface_t *surface;
11777         dp_model_t *model = ent->model;
11778         vec3_t v;
11779
11780         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11781                 return;
11782
11783         if (r_showoverdraw.value > 0)
11784         {
11785                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11786                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11787                 R_SetupShader_Generic_NoTexture(false, false);
11788                 GL_DepthTest(false);
11789                 GL_DepthMask(false);
11790                 GL_DepthRange(0, 1);
11791                 GL_BlendFunc(GL_ONE, GL_ONE);
11792                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11793                 {
11794                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11795                                 continue;
11796                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11797                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11798                         {
11799                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11800                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11801                                 if (!rsurface.texture->currentlayers->depthmask)
11802                                         GL_Color(c, 0, 0, 1.0f);
11803                                 else if (ent == r_refdef.scene.worldentity)
11804                                         GL_Color(c, c, c, 1.0f);
11805                                 else
11806                                         GL_Color(0, c, 0, 1.0f);
11807                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11808                                 RSurf_DrawBatch();
11809                         }
11810                 }
11811                 rsurface.texture = NULL;
11812         }
11813
11814         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11815
11816 //      R_Mesh_ResetTextureState();
11817         R_SetupShader_Generic_NoTexture(false, false);
11818         GL_DepthRange(0, 1);
11819         GL_DepthTest(!r_showdisabledepthtest.integer);
11820         GL_DepthMask(false);
11821         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11822
11823         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11824         {
11825                 int triangleindex;
11826                 int bihleafindex;
11827                 qboolean cullbox = false;
11828                 const q3mbrush_t *brush;
11829                 const bih_t *bih = &model->collision_bih;
11830                 const bih_leaf_t *bihleaf;
11831                 float vertex3f[3][3];
11832                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11833                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11834                 {
11835                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11836                                 continue;
11837                         switch (bihleaf->type)
11838                         {
11839                         case BIH_BRUSH:
11840                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11841                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11842                                 {
11843                                         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);
11844                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11845                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11846                                 }
11847                                 break;
11848                         case BIH_COLLISIONTRIANGLE:
11849                                 triangleindex = bihleaf->itemindex;
11850                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11851                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11852                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11853                                 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);
11854                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11855                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11856                                 break;
11857                         case BIH_RENDERTRIANGLE:
11858                                 triangleindex = bihleaf->itemindex;
11859                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11860                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11861                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11862                                 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);
11863                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11864                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11865                                 break;
11866                         }
11867                 }
11868         }
11869
11870         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11871
11872 #ifndef USE_GLES2
11873         if (r_showtris.integer && qglPolygonMode)
11874         {
11875                 if (r_showdisabledepthtest.integer)
11876                 {
11877                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11878                         GL_DepthMask(false);
11879                 }
11880                 else
11881                 {
11882                         GL_BlendFunc(GL_ONE, GL_ZERO);
11883                         GL_DepthMask(true);
11884                 }
11885                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11886                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11887                 {
11888                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11889                                 continue;
11890                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11891                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11892                         {
11893                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11894                                 if (!rsurface.texture->currentlayers->depthmask)
11895                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11896                                 else if (ent == r_refdef.scene.worldentity)
11897                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11898                                 else
11899                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11900                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11901                                 RSurf_DrawBatch();
11902                         }
11903                 }
11904                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11905                 rsurface.texture = NULL;
11906         }
11907
11908         if (r_shownormals.value != 0 && qglBegin)
11909         {
11910                 if (r_showdisabledepthtest.integer)
11911                 {
11912                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11913                         GL_DepthMask(false);
11914                 }
11915                 else
11916                 {
11917                         GL_BlendFunc(GL_ONE, GL_ZERO);
11918                         GL_DepthMask(true);
11919                 }
11920                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11921                 {
11922                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11923                                 continue;
11924                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11925                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11926                         {
11927                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11928                                 qglBegin(GL_LINES);
11929                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11930                                 {
11931                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11932                                         {
11933                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11934                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11935                                                 qglVertex3f(v[0], v[1], v[2]);
11936                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11937                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11938                                                 qglVertex3f(v[0], v[1], v[2]);
11939                                         }
11940                                 }
11941                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11942                                 {
11943                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11944                                         {
11945                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11946                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11947                                                 qglVertex3f(v[0], v[1], v[2]);
11948                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11949                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11950                                                 qglVertex3f(v[0], v[1], v[2]);
11951                                         }
11952                                 }
11953                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11954                                 {
11955                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11956                                         {
11957                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11958                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11959                                                 qglVertex3f(v[0], v[1], v[2]);
11960                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11961                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11962                                                 qglVertex3f(v[0], v[1], v[2]);
11963                                         }
11964                                 }
11965                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11966                                 {
11967                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11968                                         {
11969                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11970                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11971                                                 qglVertex3f(v[0], v[1], v[2]);
11972                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11973                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11974                                                 qglVertex3f(v[0], v[1], v[2]);
11975                                         }
11976                                 }
11977                                 qglEnd();
11978                                 CHECKGLERROR
11979                         }
11980                 }
11981                 rsurface.texture = NULL;
11982         }
11983 #endif
11984 }
11985
11986 int r_maxsurfacelist = 0;
11987 const msurface_t **r_surfacelist = NULL;
11988 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11989 {
11990         int i, j, endj, flagsmask;
11991         dp_model_t *model = r_refdef.scene.worldmodel;
11992         msurface_t *surfaces;
11993         unsigned char *update;
11994         int numsurfacelist = 0;
11995         if (model == NULL)
11996                 return;
11997
11998         if (r_maxsurfacelist < model->num_surfaces)
11999         {
12000                 r_maxsurfacelist = model->num_surfaces;
12001                 if (r_surfacelist)
12002                         Mem_Free((msurface_t**)r_surfacelist);
12003                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12004         }
12005
12006         RSurf_ActiveWorldEntity();
12007
12008         surfaces = model->data_surfaces;
12009         update = model->brushq1.lightmapupdateflags;
12010
12011         // update light styles on this submodel
12012         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12013         {
12014                 model_brush_lightstyleinfo_t *style;
12015                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12016                 {
12017                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12018                         {
12019                                 int *list = style->surfacelist;
12020                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12021                                 for (j = 0;j < style->numsurfaces;j++)
12022                                         update[list[j]] = true;
12023                         }
12024                 }
12025         }
12026
12027         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12028
12029         if (debug)
12030         {
12031                 R_DrawDebugModel();
12032                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12033                 return;
12034         }
12035
12036         rsurface.lightmaptexture = NULL;
12037         rsurface.deluxemaptexture = NULL;
12038         rsurface.uselightmaptexture = false;
12039         rsurface.texture = NULL;
12040         rsurface.rtlight = NULL;
12041         numsurfacelist = 0;
12042         // add visible surfaces to draw list
12043         for (i = 0;i < model->nummodelsurfaces;i++)
12044         {
12045                 j = model->sortedmodelsurfaces[i];
12046                 if (r_refdef.viewcache.world_surfacevisible[j])
12047                         r_surfacelist[numsurfacelist++] = surfaces + j;
12048         }
12049         // update lightmaps if needed
12050         if (model->brushq1.firstrender)
12051         {
12052                 model->brushq1.firstrender = false;
12053                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12054                         if (update[j])
12055                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12056         }
12057         else if (update)
12058         {
12059                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12060                         if (r_refdef.viewcache.world_surfacevisible[j])
12061                                 if (update[j])
12062                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12063         }
12064         // don't do anything if there were no surfaces
12065         if (!numsurfacelist)
12066         {
12067                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12068                 return;
12069         }
12070         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12071
12072         // add to stats if desired
12073         if (r_speeds.integer && !skysurfaces && !depthonly)
12074         {
12075                 r_refdef.stats.world_surfaces += numsurfacelist;
12076                 for (j = 0;j < numsurfacelist;j++)
12077                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12078         }
12079
12080         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12081 }
12082
12083 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12084 {
12085         int i, j, endj, flagsmask;
12086         dp_model_t *model = ent->model;
12087         msurface_t *surfaces;
12088         unsigned char *update;
12089         int numsurfacelist = 0;
12090         if (model == NULL)
12091                 return;
12092
12093         if (r_maxsurfacelist < model->num_surfaces)
12094         {
12095                 r_maxsurfacelist = model->num_surfaces;
12096                 if (r_surfacelist)
12097                         Mem_Free((msurface_t **)r_surfacelist);
12098                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12099         }
12100
12101         // if the model is static it doesn't matter what value we give for
12102         // wantnormals and wanttangents, so this logic uses only rules applicable
12103         // to a model, knowing that they are meaningless otherwise
12104         if (ent == r_refdef.scene.worldentity)
12105                 RSurf_ActiveWorldEntity();
12106         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12107                 RSurf_ActiveModelEntity(ent, false, false, false);
12108         else if (prepass)
12109                 RSurf_ActiveModelEntity(ent, true, true, true);
12110         else if (depthonly)
12111         {
12112                 switch (vid.renderpath)
12113                 {
12114                 case RENDERPATH_GL20:
12115                 case RENDERPATH_D3D9:
12116                 case RENDERPATH_D3D10:
12117                 case RENDERPATH_D3D11:
12118                 case RENDERPATH_SOFT:
12119                 case RENDERPATH_GLES2:
12120                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12121                         break;
12122                 case RENDERPATH_GL11:
12123                 case RENDERPATH_GL13:
12124                 case RENDERPATH_GLES1:
12125                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12126                         break;
12127                 }
12128         }
12129         else
12130         {
12131                 switch (vid.renderpath)
12132                 {
12133                 case RENDERPATH_GL20:
12134                 case RENDERPATH_D3D9:
12135                 case RENDERPATH_D3D10:
12136                 case RENDERPATH_D3D11:
12137                 case RENDERPATH_SOFT:
12138                 case RENDERPATH_GLES2:
12139                         RSurf_ActiveModelEntity(ent, true, true, false);
12140                         break;
12141                 case RENDERPATH_GL11:
12142                 case RENDERPATH_GL13:
12143                 case RENDERPATH_GLES1:
12144                         RSurf_ActiveModelEntity(ent, true, false, false);
12145                         break;
12146                 }
12147         }
12148
12149         surfaces = model->data_surfaces;
12150         update = model->brushq1.lightmapupdateflags;
12151
12152         // update light styles
12153         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12154         {
12155                 model_brush_lightstyleinfo_t *style;
12156                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12157                 {
12158                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12159                         {
12160                                 int *list = style->surfacelist;
12161                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12162                                 for (j = 0;j < style->numsurfaces;j++)
12163                                         update[list[j]] = true;
12164                         }
12165                 }
12166         }
12167
12168         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12169
12170         if (debug)
12171         {
12172                 R_DrawDebugModel();
12173                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12174                 return;
12175         }
12176
12177         rsurface.lightmaptexture = NULL;
12178         rsurface.deluxemaptexture = NULL;
12179         rsurface.uselightmaptexture = false;
12180         rsurface.texture = NULL;
12181         rsurface.rtlight = NULL;
12182         numsurfacelist = 0;
12183         // add visible surfaces to draw list
12184         for (i = 0;i < model->nummodelsurfaces;i++)
12185                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12186         // don't do anything if there were no surfaces
12187         if (!numsurfacelist)
12188         {
12189                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12190                 return;
12191         }
12192         // update lightmaps if needed
12193         if (update)
12194         {
12195                 int updated = 0;
12196                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12197                 {
12198                         if (update[j])
12199                         {
12200                                 updated++;
12201                                 R_BuildLightMap(ent, surfaces + j);
12202                         }
12203                 }
12204         }
12205
12206         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12207
12208         // add to stats if desired
12209         if (r_speeds.integer && !skysurfaces && !depthonly)
12210         {
12211                 r_refdef.stats.entities_surfaces += numsurfacelist;
12212                 for (j = 0;j < numsurfacelist;j++)
12213                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12214         }
12215
12216         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12217 }
12218
12219 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12220 {
12221         static texture_t texture;
12222         static msurface_t surface;
12223         const msurface_t *surfacelist = &surface;
12224
12225         // fake enough texture and surface state to render this geometry
12226
12227         texture.update_lastrenderframe = -1; // regenerate this texture
12228         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12229         texture.currentskinframe = skinframe;
12230         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12231         texture.offsetmapping = OFFSETMAPPING_OFF;
12232         texture.offsetscale = 1;
12233         texture.specularscalemod = 1;
12234         texture.specularpowermod = 1;
12235         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12236         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12237         // JUST GREP FOR "specularscalemod = 1".
12238
12239         surface.texture = &texture;
12240         surface.num_triangles = numtriangles;
12241         surface.num_firsttriangle = firsttriangle;
12242         surface.num_vertices = numvertices;
12243         surface.num_firstvertex = firstvertex;
12244
12245         // now render it
12246         rsurface.texture = R_GetCurrentTexture(surface.texture);
12247         rsurface.lightmaptexture = NULL;
12248         rsurface.deluxemaptexture = NULL;
12249         rsurface.uselightmaptexture = false;
12250         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12251 }
12252
12253 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)
12254 {
12255         static msurface_t surface;
12256         const msurface_t *surfacelist = &surface;
12257
12258         // fake enough texture and surface state to render this geometry
12259         surface.texture = texture;
12260         surface.num_triangles = numtriangles;
12261         surface.num_firsttriangle = firsttriangle;
12262         surface.num_vertices = numvertices;
12263         surface.num_firstvertex = firstvertex;
12264
12265         // now render it
12266         rsurface.texture = R_GetCurrentTexture(surface.texture);
12267         rsurface.lightmaptexture = NULL;
12268         rsurface.deluxemaptexture = NULL;
12269         rsurface.uselightmaptexture = false;
12270         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12271 }