]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix r_depthfirst 2 with r_glsl_skeletal 1
[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 *builtinshaderstring =
606 #include "shader_glsl.h"
607 ;
608
609 const char *builtinhlslshaderstring =
610 #include "shader_hlsl.h"
611 ;
612
613 char *glslshaderstring = NULL;
614 char *hlslshaderstring = NULL;
615
616 //=======================================================================================================================================================
617
618 typedef struct shaderpermutationinfo_s
619 {
620         const char *pretext;
621         const char *name;
622 }
623 shaderpermutationinfo_t;
624
625 typedef struct shadermodeinfo_s
626 {
627         const char *vertexfilename;
628         const char *geometryfilename;
629         const char *fragmentfilename;
630         const char *pretext;
631         const char *name;
632 }
633 shadermodeinfo_t;
634
635 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
636 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
637 {
638         {"#define USEDIFFUSE\n", " diffuse"},
639         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
640         {"#define USEVIEWTINT\n", " viewtint"},
641         {"#define USECOLORMAPPING\n", " colormapping"},
642         {"#define USESATURATION\n", " saturation"},
643         {"#define USEFOGINSIDE\n", " foginside"},
644         {"#define USEFOGOUTSIDE\n", " fogoutside"},
645         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
646         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
647         {"#define USEGAMMARAMPS\n", " gammaramps"},
648         {"#define USECUBEFILTER\n", " cubefilter"},
649         {"#define USEGLOW\n", " glow"},
650         {"#define USEBLOOM\n", " bloom"},
651         {"#define USESPECULAR\n", " specular"},
652         {"#define USEPOSTPROCESSING\n", " postprocessing"},
653         {"#define USEREFLECTION\n", " reflection"},
654         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
655         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
656         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
657         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
658         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
659         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
660         {"#define USEALPHAKILL\n", " alphakill"},
661         {"#define USEREFLECTCUBE\n", " reflectcube"},
662         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
663         {"#define USEBOUNCEGRID\n", " bouncegrid"},
664         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
665         {"#define USETRIPPY\n", " trippy"},
666         {"#define USEDEPTHRGB\n", " depthrgb"},
667         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
668         {"#define USESKELETAL\n", " skeletal"}
669 };
670
671 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
672 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
673 {
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
692 };
693
694 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
695 {
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
713         {"hlsl/default.hlsl", NULL, "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_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
979 {
980         char *shaderstring;
981         if (!filename || !filename[0])
982                 return NULL;
983         if (!strcmp(filename, "glsl/default.glsl"))
984         {
985                 if (!glslshaderstring)
986                 {
987                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
988                         if (glslshaderstring)
989                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
990                         else
991                                 glslshaderstring = (char *)builtinshaderstring;
992                 }
993                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
994                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
995                 return shaderstring;
996         }
997         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
998         if (shaderstring)
999         {
1000                 if (printfromdisknotice)
1001                         Con_DPrintf("from disk %s... ", filename);
1002                 return shaderstring;
1003         }
1004         return shaderstring;
1005 }
1006
1007 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1008 {
1009         int i;
1010         int sampler;
1011         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1012         char *vertexstring, *geometrystring, *fragmentstring;
1013         char permutationname[256];
1014         int vertstrings_count = 0;
1015         int geomstrings_count = 0;
1016         int fragstrings_count = 0;
1017         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1018         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1019         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1020
1021         if (p->compiled)
1022                 return;
1023         p->compiled = true;
1024         p->program = 0;
1025
1026         permutationname[0] = 0;
1027         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1028         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1029         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1030
1031         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1032
1033         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1034         if(vid.support.gl20shaders130)
1035         {
1036                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1037                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1038                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1039                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1040                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1041                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1042         }
1043
1044         // the first pretext is which type of shader to compile as
1045         // (later these will all be bound together as a program object)
1046         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1047         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1048         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1049
1050         // the second pretext is the mode (for example a light source)
1051         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1052         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1053         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1054         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1055
1056         // now add all the permutation pretexts
1057         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1058         {
1059                 if (permutation & (1<<i))
1060                 {
1061                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1062                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1063                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1064                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1065                 }
1066                 else
1067                 {
1068                         // keep line numbers correct
1069                         vertstrings_list[vertstrings_count++] = "\n";
1070                         geomstrings_list[geomstrings_count++] = "\n";
1071                         fragstrings_list[fragstrings_count++] = "\n";
1072                 }
1073         }
1074
1075         // add static parms
1076         R_CompileShader_AddStaticParms(mode, permutation);
1077         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1078         vertstrings_count += shaderstaticparms_count;
1079         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1080         geomstrings_count += shaderstaticparms_count;
1081         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1082         fragstrings_count += shaderstaticparms_count;
1083
1084         // now append the shader text itself
1085         vertstrings_list[vertstrings_count++] = vertexstring;
1086         geomstrings_list[geomstrings_count++] = geometrystring;
1087         fragstrings_list[fragstrings_count++] = fragmentstring;
1088
1089         // if any sources were NULL, clear the respective list
1090         if (!vertexstring)
1091                 vertstrings_count = 0;
1092         if (!geometrystring)
1093                 geomstrings_count = 0;
1094         if (!fragmentstring)
1095                 fragstrings_count = 0;
1096
1097         // compile the shader program
1098         if (vertstrings_count + geomstrings_count + fragstrings_count)
1099                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1100         if (p->program)
1101         {
1102                 CHECKGLERROR
1103                 qglUseProgram(p->program);CHECKGLERROR
1104                 // look up all the uniform variable names we care about, so we don't
1105                 // have to look them up every time we set them
1106
1107                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1108                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1109                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1110                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1111                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1112                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1113                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1114                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1115                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1116                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1117                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1118                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1119                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1120                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1121                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1122                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1123                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1124                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1125                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1126                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1127                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1128                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1129                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1130                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1131                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1132                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1133                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1134                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1135                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1136                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1137                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1138                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1139                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1140                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1141                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1142                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1143                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1144                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1145                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1146                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1147                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1148                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1149                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1150                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1151                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1152                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1153                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1154                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1155                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1156                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1157                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1158                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1159                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1160                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1161                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1162                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1163                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1164                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1165                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1166                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1167                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1168                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1169                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1170                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1171                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1172                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1173                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1174                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1175                 p->loc_Skeletal_Transform12       = qglGetUniformLocation(p->program, "Skeletal_Transform12");
1176                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1177                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1178                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1179                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1180                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1181                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1182                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1183                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1184                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1185                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1186                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1187                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1188                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1189                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1190                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1191                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1192                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1193                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1194                 // initialize the samplers to refer to the texture units we use
1195                 p->tex_Texture_First = -1;
1196                 p->tex_Texture_Second = -1;
1197                 p->tex_Texture_GammaRamps = -1;
1198                 p->tex_Texture_Normal = -1;
1199                 p->tex_Texture_Color = -1;
1200                 p->tex_Texture_Gloss = -1;
1201                 p->tex_Texture_Glow = -1;
1202                 p->tex_Texture_SecondaryNormal = -1;
1203                 p->tex_Texture_SecondaryColor = -1;
1204                 p->tex_Texture_SecondaryGloss = -1;
1205                 p->tex_Texture_SecondaryGlow = -1;
1206                 p->tex_Texture_Pants = -1;
1207                 p->tex_Texture_Shirt = -1;
1208                 p->tex_Texture_FogHeightTexture = -1;
1209                 p->tex_Texture_FogMask = -1;
1210                 p->tex_Texture_Lightmap = -1;
1211                 p->tex_Texture_Deluxemap = -1;
1212                 p->tex_Texture_Attenuation = -1;
1213                 p->tex_Texture_Cube = -1;
1214                 p->tex_Texture_Refraction = -1;
1215                 p->tex_Texture_Reflection = -1;
1216                 p->tex_Texture_ShadowMap2D = -1;
1217                 p->tex_Texture_CubeProjection = -1;
1218                 p->tex_Texture_ScreenNormalMap = -1;
1219                 p->tex_Texture_ScreenDiffuse = -1;
1220                 p->tex_Texture_ScreenSpecular = -1;
1221                 p->tex_Texture_ReflectMask = -1;
1222                 p->tex_Texture_ReflectCube = -1;
1223                 p->tex_Texture_BounceGrid = -1;
1224                 sampler = 0;
1225                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1226                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1227                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1228                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1229                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1230                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1231                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1232                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1233                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1234                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1235                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1236                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1237                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1238                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1239                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1240                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1241                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1242                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1243                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1244                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1245                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1246                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1247                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1248                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1249                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1250                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1251                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1252                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1253                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1254                 CHECKGLERROR
1255                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1256         }
1257         else
1258                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1259
1260         // free the strings
1261         if (vertexstring)
1262                 Mem_Free(vertexstring);
1263         if (geometrystring)
1264                 Mem_Free(geometrystring);
1265         if (fragmentstring)
1266                 Mem_Free(fragmentstring);
1267 }
1268
1269 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1270 {
1271         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1272         if (r_glsl_permutation != perm)
1273         {
1274                 r_glsl_permutation = perm;
1275                 if (!r_glsl_permutation->program)
1276                 {
1277                         if (!r_glsl_permutation->compiled)
1278                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1279                         if (!r_glsl_permutation->program)
1280                         {
1281                                 // remove features until we find a valid permutation
1282                                 int i;
1283                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1284                                 {
1285                                         // reduce i more quickly whenever it would not remove any bits
1286                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1287                                         if (!(permutation & j))
1288                                                 continue;
1289                                         permutation -= j;
1290                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1291                                         if (!r_glsl_permutation->compiled)
1292                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1293                                         if (r_glsl_permutation->program)
1294                                                 break;
1295                                 }
1296                                 if (i >= SHADERPERMUTATION_COUNT)
1297                                 {
1298                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1299                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1300                                         qglUseProgram(0);CHECKGLERROR
1301                                         return; // no bit left to clear, entire mode is broken
1302                                 }
1303                         }
1304                 }
1305                 CHECKGLERROR
1306                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1307         }
1308         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1309         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1310         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1311 }
1312
1313 #ifdef SUPPORTD3D
1314
1315 #ifdef SUPPORTD3D
1316 #include <d3d9.h>
1317 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1318 extern D3DCAPS9 vid_d3d9caps;
1319 #endif
1320
1321 struct r_hlsl_permutation_s;
1322 typedef struct r_hlsl_permutation_s
1323 {
1324         /// hash lookup data
1325         struct r_hlsl_permutation_s *hashnext;
1326         unsigned int mode;
1327         unsigned int permutation;
1328
1329         /// indicates if we have tried compiling this permutation already
1330         qboolean compiled;
1331         /// NULL if compilation failed
1332         IDirect3DVertexShader9 *vertexshader;
1333         IDirect3DPixelShader9 *pixelshader;
1334 }
1335 r_hlsl_permutation_t;
1336
1337 typedef enum D3DVSREGISTER_e
1338 {
1339         D3DVSREGISTER_TexMatrix = 0, // float4x4
1340         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1341         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1342         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1343         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1344         D3DVSREGISTER_ModelToLight = 20, // float4x4
1345         D3DVSREGISTER_EyePosition = 24,
1346         D3DVSREGISTER_FogPlane = 25,
1347         D3DVSREGISTER_LightDir = 26,
1348         D3DVSREGISTER_LightPosition = 27,
1349 }
1350 D3DVSREGISTER_t;
1351
1352 typedef enum D3DPSREGISTER_e
1353 {
1354         D3DPSREGISTER_Alpha = 0,
1355         D3DPSREGISTER_BloomBlur_Parameters = 1,
1356         D3DPSREGISTER_ClientTime = 2,
1357         D3DPSREGISTER_Color_Ambient = 3,
1358         D3DPSREGISTER_Color_Diffuse = 4,
1359         D3DPSREGISTER_Color_Specular = 5,
1360         D3DPSREGISTER_Color_Glow = 6,
1361         D3DPSREGISTER_Color_Pants = 7,
1362         D3DPSREGISTER_Color_Shirt = 8,
1363         D3DPSREGISTER_DeferredColor_Ambient = 9,
1364         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1365         D3DPSREGISTER_DeferredColor_Specular = 11,
1366         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1367         D3DPSREGISTER_DeferredMod_Specular = 13,
1368         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1369         D3DPSREGISTER_EyePosition = 15, // unused
1370         D3DPSREGISTER_FogColor = 16,
1371         D3DPSREGISTER_FogHeightFade = 17,
1372         D3DPSREGISTER_FogPlane = 18,
1373         D3DPSREGISTER_FogPlaneViewDist = 19,
1374         D3DPSREGISTER_FogRangeRecip = 20,
1375         D3DPSREGISTER_LightColor = 21,
1376         D3DPSREGISTER_LightDir = 22, // unused
1377         D3DPSREGISTER_LightPosition = 23,
1378         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1379         D3DPSREGISTER_PixelSize = 25,
1380         D3DPSREGISTER_ReflectColor = 26,
1381         D3DPSREGISTER_ReflectFactor = 27,
1382         D3DPSREGISTER_ReflectOffset = 28,
1383         D3DPSREGISTER_RefractColor = 29,
1384         D3DPSREGISTER_Saturation = 30,
1385         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1386         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1387         D3DPSREGISTER_ScreenToDepth = 33,
1388         D3DPSREGISTER_ShadowMap_Parameters = 34,
1389         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1390         D3DPSREGISTER_SpecularPower = 36,
1391         D3DPSREGISTER_UserVec1 = 37,
1392         D3DPSREGISTER_UserVec2 = 38,
1393         D3DPSREGISTER_UserVec3 = 39,
1394         D3DPSREGISTER_UserVec4 = 40,
1395         D3DPSREGISTER_ViewTintColor = 41,
1396         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1397         D3DPSREGISTER_BloomColorSubtract = 43,
1398         D3DPSREGISTER_ViewToLight = 44, // float4x4
1399         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1400         D3DPSREGISTER_NormalmapScrollBlend = 52,
1401         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1402         D3DPSREGISTER_OffsetMapping_Bias = 54,
1403         // next at 54
1404 }
1405 D3DPSREGISTER_t;
1406
1407 /// information about each possible shader permutation
1408 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1409 /// currently selected permutation
1410 r_hlsl_permutation_t *r_hlsl_permutation;
1411 /// storage for permutations linked in the hash table
1412 memexpandablearray_t r_hlsl_permutationarray;
1413
1414 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1415 {
1416         //unsigned int hashdepth = 0;
1417         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1418         r_hlsl_permutation_t *p;
1419         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1420         {
1421                 if (p->mode == mode && p->permutation == permutation)
1422                 {
1423                         //if (hashdepth > 10)
1424                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1425                         return p;
1426                 }
1427                 //hashdepth++;
1428         }
1429         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1430         p->mode = mode;
1431         p->permutation = permutation;
1432         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1433         r_hlsl_permutationhash[mode][hashindex] = p;
1434         //if (hashdepth > 10)
1435         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1436         return p;
1437 }
1438
1439 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1440 {
1441         char *shaderstring;
1442         if (!filename || !filename[0])
1443                 return NULL;
1444         if (!strcmp(filename, "hlsl/default.hlsl"))
1445         {
1446                 if (!hlslshaderstring)
1447                 {
1448                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1449                         if (hlslshaderstring)
1450                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1451                         else
1452                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1453                 }
1454                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1455                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1456                 return shaderstring;
1457         }
1458         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1459         if (shaderstring)
1460         {
1461                 if (printfromdisknotice)
1462                         Con_DPrintf("from disk %s... ", filename);
1463                 return shaderstring;
1464         }
1465         return shaderstring;
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                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1537                 {
1538                         DWORD shaderflags = 0;
1539                         if (debugshader)
1540                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1541                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1542                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1543                         if (vertstring && vertstring[0])
1544                         {
1545                                 if (debugshader)
1546                                 {
1547                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1548                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1549                                 }
1550                                 else
1551                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1552                                 if (vsbuffer)
1553                                 {
1554                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1555                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1556                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1557                                         ID3DXBuffer_Release(vsbuffer);
1558                                 }
1559                                 if (vslog)
1560                                 {
1561                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1562                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1563                                         ID3DXBuffer_Release(vslog);
1564                                 }
1565                         }
1566                         if (fragstring && fragstring[0])
1567                         {
1568                                 if (debugshader)
1569                                 {
1570                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1571                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1572                                 }
1573                                 else
1574                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1575                                 if (psbuffer)
1576                                 {
1577                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1578                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1579                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1580                                         ID3DXBuffer_Release(psbuffer);
1581                                 }
1582                                 if (pslog)
1583                                 {
1584                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1585                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1586                                         ID3DXBuffer_Release(pslog);
1587                                 }
1588                         }
1589                         Sys_UnloadLibrary(&d3dx9_dll);
1590                 }
1591                 else
1592                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1593         }
1594         if (vsbin && psbin)
1595         {
1596                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1597                 if (FAILED(vsresult))
1598                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1599                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1600                 if (FAILED(psresult))
1601                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1602         }
1603         // free the shader data
1604         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1605         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1606 }
1607
1608 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1609 {
1610         int i;
1611         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1612         int vertstring_length = 0;
1613         int geomstring_length = 0;
1614         int fragstring_length = 0;
1615         char *t;
1616         char *vertexstring, *geometrystring, *fragmentstring;
1617         char *vertstring, *geomstring, *fragstring;
1618         char permutationname[256];
1619         char cachename[256];
1620         int vertstrings_count = 0;
1621         int geomstrings_count = 0;
1622         int fragstrings_count = 0;
1623         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1624         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1625         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1626
1627         if (p->compiled)
1628                 return;
1629         p->compiled = true;
1630         p->vertexshader = NULL;
1631         p->pixelshader = NULL;
1632
1633         permutationname[0] = 0;
1634         cachename[0] = 0;
1635         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1636         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1637         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1638
1639         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1640         strlcat(cachename, "hlsl/", sizeof(cachename));
1641
1642         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1643         vertstrings_count = 0;
1644         geomstrings_count = 0;
1645         fragstrings_count = 0;
1646         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1647         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1648         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1649
1650         // the first pretext is which type of shader to compile as
1651         // (later these will all be bound together as a program object)
1652         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1653         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1654         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1655
1656         // the second pretext is the mode (for example a light source)
1657         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1658         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1659         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1660         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1661         strlcat(cachename, modeinfo->name, sizeof(cachename));
1662
1663         // now add all the permutation pretexts
1664         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1665         {
1666                 if (permutation & (1<<i))
1667                 {
1668                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1669                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1670                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1671                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1672                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1673                 }
1674                 else
1675                 {
1676                         // keep line numbers correct
1677                         vertstrings_list[vertstrings_count++] = "\n";
1678                         geomstrings_list[geomstrings_count++] = "\n";
1679                         fragstrings_list[fragstrings_count++] = "\n";
1680                 }
1681         }
1682
1683         // add static parms
1684         R_CompileShader_AddStaticParms(mode, permutation);
1685         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1686         vertstrings_count += shaderstaticparms_count;
1687         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1688         geomstrings_count += shaderstaticparms_count;
1689         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1690         fragstrings_count += shaderstaticparms_count;
1691
1692         // replace spaces in the cachename with _ characters
1693         for (i = 0;cachename[i];i++)
1694                 if (cachename[i] == ' ')
1695                         cachename[i] = '_';
1696
1697         // now append the shader text itself
1698         vertstrings_list[vertstrings_count++] = vertexstring;
1699         geomstrings_list[geomstrings_count++] = geometrystring;
1700         fragstrings_list[fragstrings_count++] = fragmentstring;
1701
1702         // if any sources were NULL, clear the respective list
1703         if (!vertexstring)
1704                 vertstrings_count = 0;
1705         if (!geometrystring)
1706                 geomstrings_count = 0;
1707         if (!fragmentstring)
1708                 fragstrings_count = 0;
1709
1710         vertstring_length = 0;
1711         for (i = 0;i < vertstrings_count;i++)
1712                 vertstring_length += strlen(vertstrings_list[i]);
1713         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1714         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1715                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1716
1717         geomstring_length = 0;
1718         for (i = 0;i < geomstrings_count;i++)
1719                 geomstring_length += strlen(geomstrings_list[i]);
1720         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1721         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1722                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1723
1724         fragstring_length = 0;
1725         for (i = 0;i < fragstrings_count;i++)
1726                 fragstring_length += strlen(fragstrings_list[i]);
1727         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1728         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1729                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1730
1731         // try to load the cached shader, or generate one
1732         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1733
1734         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1735                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1736         else
1737                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1738
1739         // free the strings
1740         if (vertstring)
1741                 Mem_Free(vertstring);
1742         if (geomstring)
1743                 Mem_Free(geomstring);
1744         if (fragstring)
1745                 Mem_Free(fragstring);
1746         if (vertexstring)
1747                 Mem_Free(vertexstring);
1748         if (geometrystring)
1749                 Mem_Free(geometrystring);
1750         if (fragmentstring)
1751                 Mem_Free(fragmentstring);
1752 }
1753
1754 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1755 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1756 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);}
1757 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);}
1758 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);}
1759 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);}
1760
1761 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1762 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1763 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);}
1764 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);}
1765 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);}
1766 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);}
1767
1768 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1769 {
1770         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1771         if (r_hlsl_permutation != perm)
1772         {
1773                 r_hlsl_permutation = perm;
1774                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1775                 {
1776                         if (!r_hlsl_permutation->compiled)
1777                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1778                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1779                         {
1780                                 // remove features until we find a valid permutation
1781                                 int i;
1782                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1783                                 {
1784                                         // reduce i more quickly whenever it would not remove any bits
1785                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1786                                         if (!(permutation & j))
1787                                                 continue;
1788                                         permutation -= j;
1789                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1790                                         if (!r_hlsl_permutation->compiled)
1791                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1792                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1793                                                 break;
1794                                 }
1795                                 if (i >= SHADERPERMUTATION_COUNT)
1796                                 {
1797                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1798                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1799                                         return; // no bit left to clear, entire mode is broken
1800                                 }
1801                         }
1802                 }
1803                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1804                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1805         }
1806         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1807         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1808         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1809 }
1810 #endif
1811
1812 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1813 {
1814         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1815         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1816         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1817         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1818 }
1819
1820 void R_GLSL_Restart_f(void)
1821 {
1822         unsigned int i, limit;
1823         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1824                 Mem_Free(glslshaderstring);
1825         glslshaderstring = NULL;
1826         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1827                 Mem_Free(hlslshaderstring);
1828         hlslshaderstring = NULL;
1829         switch(vid.renderpath)
1830         {
1831         case RENDERPATH_D3D9:
1832 #ifdef SUPPORTD3D
1833                 {
1834                         r_hlsl_permutation_t *p;
1835                         r_hlsl_permutation = NULL;
1836                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1837                         for (i = 0;i < limit;i++)
1838                         {
1839                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1840                                 {
1841                                         if (p->vertexshader)
1842                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1843                                         if (p->pixelshader)
1844                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1845                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1846                                 }
1847                         }
1848                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1849                 }
1850 #endif
1851                 break;
1852         case RENDERPATH_D3D10:
1853                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1854                 break;
1855         case RENDERPATH_D3D11:
1856                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1857                 break;
1858         case RENDERPATH_GL20:
1859         case RENDERPATH_GLES2:
1860                 {
1861                         r_glsl_permutation_t *p;
1862                         r_glsl_permutation = NULL;
1863                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1864                         for (i = 0;i < limit;i++)
1865                         {
1866                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1867                                 {
1868                                         GL_Backend_FreeProgram(p->program);
1869                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1870                                 }
1871                         }
1872                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1873                 }
1874                 break;
1875         case RENDERPATH_GL11:
1876         case RENDERPATH_GL13:
1877         case RENDERPATH_GLES1:
1878                 break;
1879         case RENDERPATH_SOFT:
1880                 break;
1881         }
1882 }
1883
1884 static void R_GLSL_DumpShader_f(void)
1885 {
1886         int i;
1887         qfile_t *file;
1888
1889         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1890         if (file)
1891         {
1892                 FS_Print(file, "/* The engine may define the following macros:\n");
1893                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1894                 for (i = 0;i < SHADERMODE_COUNT;i++)
1895                         FS_Print(file, glslshadermodeinfo[i].pretext);
1896                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1897                         FS_Print(file, shaderpermutationinfo[i].pretext);
1898                 FS_Print(file, "*/\n");
1899                 FS_Print(file, builtinshaderstring);
1900                 FS_Close(file);
1901                 Con_Printf("glsl/default.glsl written\n");
1902         }
1903         else
1904                 Con_Printf("failed to write to glsl/default.glsl\n");
1905
1906         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1907         if (file)
1908         {
1909                 FS_Print(file, "/* The engine may define the following macros:\n");
1910                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1911                 for (i = 0;i < SHADERMODE_COUNT;i++)
1912                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1913                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1914                         FS_Print(file, shaderpermutationinfo[i].pretext);
1915                 FS_Print(file, "*/\n");
1916                 FS_Print(file, builtinhlslshaderstring);
1917                 FS_Close(file);
1918                 Con_Printf("hlsl/default.hlsl written\n");
1919         }
1920         else
1921                 Con_Printf("failed to write to hlsl/default.hlsl\n");
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 void R_SetupShader_ShowDepth(qboolean notrippy)
2041 {
2042         int permutation = 0;
2043         if (r_trippy.integer && !notrippy)
2044                 permutation |= SHADERPERMUTATION_TRIPPY;
2045         if (vid.allowalphatocoverage)
2046                 GL_AlphaToCoverage(false);
2047         switch (vid.renderpath)
2048         {
2049         case RENDERPATH_D3D9:
2050 #ifdef SUPPORTHLSL
2051                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2052 #endif
2053                 break;
2054         case RENDERPATH_D3D10:
2055                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2056                 break;
2057         case RENDERPATH_D3D11:
2058                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2059                 break;
2060         case RENDERPATH_GL20:
2061         case RENDERPATH_GLES2:
2062                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2063                 break;
2064         case RENDERPATH_GL13:
2065         case RENDERPATH_GLES1:
2066                 break;
2067         case RENDERPATH_GL11:
2068                 break;
2069         case RENDERPATH_SOFT:
2070                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2071                 break;
2072         }
2073 }
2074
2075 extern qboolean r_shadow_usingdeferredprepass;
2076 extern rtexture_t *r_shadow_attenuationgradienttexture;
2077 extern rtexture_t *r_shadow_attenuation2dtexture;
2078 extern rtexture_t *r_shadow_attenuation3dtexture;
2079 extern qboolean r_shadow_usingshadowmap2d;
2080 extern qboolean r_shadow_usingshadowmaportho;
2081 extern float r_shadow_shadowmap_texturescale[2];
2082 extern float r_shadow_shadowmap_parameters[4];
2083 extern qboolean r_shadow_shadowmapvsdct;
2084 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2085 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2086 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2087 extern matrix4x4_t r_shadow_shadowmapmatrix;
2088 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2089 extern int r_shadow_prepass_width;
2090 extern int r_shadow_prepass_height;
2091 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2092 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2093 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2094 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2095
2096 #define BLENDFUNC_ALLOWS_COLORMOD      1
2097 #define BLENDFUNC_ALLOWS_FOG           2
2098 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2099 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2100 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2101 static int R_BlendFuncFlags(int src, int dst)
2102 {
2103         int r = 0;
2104
2105         // a blendfunc allows colormod if:
2106         // a) it can never keep the destination pixel invariant, or
2107         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2108         // this is to prevent unintended side effects from colormod
2109
2110         // a blendfunc allows fog if:
2111         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2112         // this is to prevent unintended side effects from fog
2113
2114         // these checks are the output of fogeval.pl
2115
2116         r |= BLENDFUNC_ALLOWS_COLORMOD;
2117         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2118         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2119         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2120         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2121         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2122         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2123         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2124         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2125         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2126         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2127         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2128         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2129         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2130         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2131         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2132         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2133         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2134         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2135         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2136         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2137         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2138
2139         return r;
2140 }
2141
2142 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)
2143 {
2144         // select a permutation of the lighting shader appropriate to this
2145         // combination of texture, entity, light source, and fogging, only use the
2146         // minimum features necessary to avoid wasting rendering time in the
2147         // fragment shader on features that are not being used
2148         unsigned int permutation = 0;
2149         unsigned int mode = 0;
2150         int blendfuncflags;
2151         static float dummy_colormod[3] = {1, 1, 1};
2152         float *colormod = rsurface.colormod;
2153         float m16f[16];
2154         matrix4x4_t tempmatrix;
2155         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2156         if (r_trippy.integer && !notrippy)
2157                 permutation |= SHADERPERMUTATION_TRIPPY;
2158         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2159                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2160         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2161                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2162         if (rsurfacepass == RSURFPASS_BACKGROUND)
2163         {
2164                 // distorted background
2165                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2166                 {
2167                         mode = SHADERMODE_WATER;
2168                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2169                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2170                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2171                         {
2172                                 // this is the right thing to do for wateralpha
2173                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2174                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2175                         }
2176                         else
2177                         {
2178                                 // this is the right thing to do for entity alpha
2179                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2180                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2181                         }
2182                 }
2183                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2184                 {
2185                         mode = SHADERMODE_REFRACTION;
2186                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2187                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2188                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2189                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2190                 }
2191                 else
2192                 {
2193                         mode = SHADERMODE_GENERIC;
2194                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2195                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2196                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2197                 }
2198                 if (vid.allowalphatocoverage)
2199                         GL_AlphaToCoverage(false);
2200         }
2201         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2202         {
2203                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2204                 {
2205                         switch(rsurface.texture->offsetmapping)
2206                         {
2207                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2208                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2209                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2210                         case OFFSETMAPPING_OFF: break;
2211                         }
2212                 }
2213                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2214                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2215                 // normalmap (deferred prepass), may use alpha test on diffuse
2216                 mode = SHADERMODE_DEFERREDGEOMETRY;
2217                 GL_BlendFunc(GL_ONE, GL_ZERO);
2218                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2219                 if (vid.allowalphatocoverage)
2220                         GL_AlphaToCoverage(false);
2221         }
2222         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2223         {
2224                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2225                 {
2226                         switch(rsurface.texture->offsetmapping)
2227                         {
2228                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2229                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2230                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2231                         case OFFSETMAPPING_OFF: break;
2232                         }
2233                 }
2234                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2235                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2236                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2237                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2238                 // light source
2239                 mode = SHADERMODE_LIGHTSOURCE;
2240                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2241                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2242                 if (diffusescale > 0)
2243                         permutation |= SHADERPERMUTATION_DIFFUSE;
2244                 if (specularscale > 0)
2245                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2246                 if (r_refdef.fogenabled)
2247                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2248                 if (rsurface.texture->colormapping)
2249                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2250                 if (r_shadow_usingshadowmap2d)
2251                 {
2252                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2253                         if(r_shadow_shadowmapvsdct)
2254                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2255
2256                         if (r_shadow_shadowmap2ddepthbuffer)
2257                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2258                 }
2259                 if (rsurface.texture->reflectmasktexture)
2260                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2261                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2262                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2263                 if (vid.allowalphatocoverage)
2264                         GL_AlphaToCoverage(false);
2265         }
2266         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2267         {
2268                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2269                 {
2270                         switch(rsurface.texture->offsetmapping)
2271                         {
2272                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2273                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2274                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2275                         case OFFSETMAPPING_OFF: break;
2276                         }
2277                 }
2278                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2279                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2280                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2281                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2282                 // unshaded geometry (fullbright or ambient model lighting)
2283                 mode = SHADERMODE_FLATCOLOR;
2284                 ambientscale = diffusescale = specularscale = 0;
2285                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2286                         permutation |= SHADERPERMUTATION_GLOW;
2287                 if (r_refdef.fogenabled)
2288                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2289                 if (rsurface.texture->colormapping)
2290                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2291                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2292                 {
2293                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2294                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2295
2296                         if (r_shadow_shadowmap2ddepthbuffer)
2297                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2298                 }
2299                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2300                         permutation |= SHADERPERMUTATION_REFLECTION;
2301                 if (rsurface.texture->reflectmasktexture)
2302                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2303                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2304                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2305                 // when using alphatocoverage, we don't need alphakill
2306                 if (vid.allowalphatocoverage)
2307                 {
2308                         if (r_transparent_alphatocoverage.integer)
2309                         {
2310                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2311                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2312                         }
2313                         else
2314                                 GL_AlphaToCoverage(false);
2315                 }
2316         }
2317         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2318         {
2319                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2320                 {
2321                         switch(rsurface.texture->offsetmapping)
2322                         {
2323                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2324                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2325                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2326                         case OFFSETMAPPING_OFF: break;
2327                         }
2328                 }
2329                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2330                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2331                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2332                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2333                 // directional model lighting
2334                 mode = SHADERMODE_LIGHTDIRECTION;
2335                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2336                         permutation |= SHADERPERMUTATION_GLOW;
2337                 permutation |= SHADERPERMUTATION_DIFFUSE;
2338                 if (specularscale > 0)
2339                         permutation |= SHADERPERMUTATION_SPECULAR;
2340                 if (r_refdef.fogenabled)
2341                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2342                 if (rsurface.texture->colormapping)
2343                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2344                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2345                 {
2346                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2347                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2348
2349                         if (r_shadow_shadowmap2ddepthbuffer)
2350                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2351                 }
2352                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2353                         permutation |= SHADERPERMUTATION_REFLECTION;
2354                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2355                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2356                 if (rsurface.texture->reflectmasktexture)
2357                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2358                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2359                 {
2360                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2361                         if (r_shadow_bouncegriddirectional)
2362                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2363                 }
2364                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2365                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2366                 // when using alphatocoverage, we don't need alphakill
2367                 if (vid.allowalphatocoverage)
2368                 {
2369                         if (r_transparent_alphatocoverage.integer)
2370                         {
2371                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2372                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2373                         }
2374                         else
2375                                 GL_AlphaToCoverage(false);
2376                 }
2377         }
2378         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2379         {
2380                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2381                 {
2382                         switch(rsurface.texture->offsetmapping)
2383                         {
2384                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2385                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2386                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2387                         case OFFSETMAPPING_OFF: break;
2388                         }
2389                 }
2390                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2391                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2392                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2393                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2394                 // ambient model lighting
2395                 mode = SHADERMODE_LIGHTDIRECTION;
2396                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2397                         permutation |= SHADERPERMUTATION_GLOW;
2398                 if (r_refdef.fogenabled)
2399                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2400                 if (rsurface.texture->colormapping)
2401                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2402                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2403                 {
2404                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2405                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2406
2407                         if (r_shadow_shadowmap2ddepthbuffer)
2408                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2409                 }
2410                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2411                         permutation |= SHADERPERMUTATION_REFLECTION;
2412                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2413                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2414                 if (rsurface.texture->reflectmasktexture)
2415                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2416                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2417                 {
2418                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2419                         if (r_shadow_bouncegriddirectional)
2420                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2421                 }
2422                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2423                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2424                 // when using alphatocoverage, we don't need alphakill
2425                 if (vid.allowalphatocoverage)
2426                 {
2427                         if (r_transparent_alphatocoverage.integer)
2428                         {
2429                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2430                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2431                         }
2432                         else
2433                                 GL_AlphaToCoverage(false);
2434                 }
2435         }
2436         else
2437         {
2438                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2439                 {
2440                         switch(rsurface.texture->offsetmapping)
2441                         {
2442                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2443                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2444                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2445                         case OFFSETMAPPING_OFF: break;
2446                         }
2447                 }
2448                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2449                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2450                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2451                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2452                 // lightmapped wall
2453                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2454                         permutation |= SHADERPERMUTATION_GLOW;
2455                 if (r_refdef.fogenabled)
2456                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2457                 if (rsurface.texture->colormapping)
2458                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2459                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2460                 {
2461                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2462                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2463
2464                         if (r_shadow_shadowmap2ddepthbuffer)
2465                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2466                 }
2467                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2468                         permutation |= SHADERPERMUTATION_REFLECTION;
2469                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2470                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2471                 if (rsurface.texture->reflectmasktexture)
2472                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2473                 if (FAKELIGHT_ENABLED)
2474                 {
2475                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2476                         mode = SHADERMODE_FAKELIGHT;
2477                         permutation |= SHADERPERMUTATION_DIFFUSE;
2478                         if (specularscale > 0)
2479                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2480                 }
2481                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2482                 {
2483                         // deluxemapping (light direction texture)
2484                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2485                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2486                         else
2487                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2488                         permutation |= SHADERPERMUTATION_DIFFUSE;
2489                         if (specularscale > 0)
2490                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2491                 }
2492                 else if (r_glsl_deluxemapping.integer >= 2)
2493                 {
2494                         // fake deluxemapping (uniform light direction in tangentspace)
2495                         if (rsurface.uselightmaptexture)
2496                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2497                         else
2498                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2499                         permutation |= SHADERPERMUTATION_DIFFUSE;
2500                         if (specularscale > 0)
2501                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2502                 }
2503                 else if (rsurface.uselightmaptexture)
2504                 {
2505                         // ordinary lightmapping (q1bsp, q3bsp)
2506                         mode = SHADERMODE_LIGHTMAP;
2507                 }
2508                 else
2509                 {
2510                         // ordinary vertex coloring (q3bsp)
2511                         mode = SHADERMODE_VERTEXCOLOR;
2512                 }
2513                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2514                 {
2515                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2516                         if (r_shadow_bouncegriddirectional)
2517                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2518                 }
2519                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2520                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2521                 // when using alphatocoverage, we don't need alphakill
2522                 if (vid.allowalphatocoverage)
2523                 {
2524                         if (r_transparent_alphatocoverage.integer)
2525                         {
2526                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2527                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2528                         }
2529                         else
2530                                 GL_AlphaToCoverage(false);
2531                 }
2532         }
2533         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2534                 colormod = dummy_colormod;
2535         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2536                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2537         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2538                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2539         switch(vid.renderpath)
2540         {
2541         case RENDERPATH_D3D9:
2542 #ifdef SUPPORTD3D
2543                 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);
2544                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2545                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2546                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2547                 if (mode == SHADERMODE_LIGHTSOURCE)
2548                 {
2549                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2550                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2551                 }
2552                 else
2553                 {
2554                         if (mode == SHADERMODE_LIGHTDIRECTION)
2555                         {
2556                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2557                         }
2558                 }
2559                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2560                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2561                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2562                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2563                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2564
2565                 if (mode == SHADERMODE_LIGHTSOURCE)
2566                 {
2567                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2568                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2569                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2570                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2571                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2572
2573                         // additive passes are only darkened by fog, not tinted
2574                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2575                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2576                 }
2577                 else
2578                 {
2579                         if (mode == SHADERMODE_FLATCOLOR)
2580                         {
2581                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2582                         }
2583                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2584                         {
2585                                 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]);
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2587                                 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);
2588                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2589                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2590                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2591                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2592                         }
2593                         else
2594                         {
2595                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2596                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2597                                 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);
2598                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2599                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2600                         }
2601                         // additive passes are only darkened by fog, not tinted
2602                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2603                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2604                         else
2605                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2606                         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);
2607                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2608                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2609                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2610                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2611                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2612                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2613                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2614                         if (mode == SHADERMODE_WATER)
2615                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2616                 }
2617                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2618                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2619                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2620                 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));
2621                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2622                 if (rsurface.texture->pantstexture)
2623                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2624                 else
2625                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2626                 if (rsurface.texture->shirttexture)
2627                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2628                 else
2629                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2630                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2631                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2632                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2633                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2634                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2635                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2636                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2637                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2638                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2639                         );
2640                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2641                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2642                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2643                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2644
2645                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2646                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2647                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2648                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2649                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2650                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2651                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2652                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2653                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2654                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2655                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2656                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2657                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2658                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2659                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2660                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2661                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2662                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2663                 {
2664                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2665                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2666                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2667                 }
2668                 else
2669                 {
2670                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2671                 }
2672 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2673                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2674                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2675                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2676                 {
2677                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2678                         if (rsurface.rtlight)
2679                         {
2680                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2681                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2682                         }
2683                 }
2684 #endif
2685                 break;
2686         case RENDERPATH_D3D10:
2687                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2688                 break;
2689         case RENDERPATH_D3D11:
2690                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2691                 break;
2692         case RENDERPATH_GL20:
2693         case RENDERPATH_GLES2:
2694                 if (!vid.useinterleavedarrays)
2695                 {
2696                         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);
2697                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2698                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2699                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2700                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2701                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2702                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2703                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2704                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2705                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2706                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2707                 }
2708                 else
2709                 {
2710                         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);
2711                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2712                 }
2713                 // this has to be after RSurf_PrepareVerticesForBatch
2714                 if (rsurface.batchskeletaltransform3x4)
2715                         permutation |= SHADERPERMUTATION_SKELETAL;
2716                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2717                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2718                 if (mode == SHADERMODE_LIGHTSOURCE)
2719                 {
2720                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2721                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2722                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2723                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2724                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2725                         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);
2726         
2727                         // additive passes are only darkened by fog, not tinted
2728                         if (r_glsl_permutation->loc_FogColor >= 0)
2729                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2730                         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);
2731                 }
2732                 else
2733                 {
2734                         if (mode == SHADERMODE_FLATCOLOR)
2735                         {
2736                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2737                         }
2738                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2739                         {
2740                                 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]);
2741                                 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]);
2742                                 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);
2743                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2744                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2745                                 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]);
2746                                 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]);
2747                         }
2748                         else
2749                         {
2750                                 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]);
2751                                 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]);
2752                                 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);
2753                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2754                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2755                         }
2756                         // additive passes are only darkened by fog, not tinted
2757                         if (r_glsl_permutation->loc_FogColor >= 0)
2758                         {
2759                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2760                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2761                                 else
2762                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2763                         }
2764                         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);
2765                         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]);
2766                         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]);
2767                         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]);
2768                         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]);
2769                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2770                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2771                         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);
2772                         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]);
2773                 }
2774                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2775                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2776                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2777                 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]);
2778                 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]);
2779
2780                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2781                 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));
2782                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2783                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2784                 {
2785                         if (rsurface.texture->pantstexture)
2786                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2787                         else
2788                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2789                 }
2790                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2791                 {
2792                         if (rsurface.texture->shirttexture)
2793                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2794                         else
2795                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2796                 }
2797                 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]);
2798                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2799                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2800                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2801                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2802                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2803                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2804                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2805                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2806                         );
2807                 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);
2808                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2809                 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]);
2810                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2811                 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);}
2812                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2813
2814                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2815                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2816                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2817                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2818                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2819                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2820                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2821                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2822                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2823                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2824                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2825                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2826                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2827                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2828                 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);
2829                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2830                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2831                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2832                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2833                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2834                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2835                 {
2836                         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);
2837                         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);
2838                         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);
2839                 }
2840                 else
2841                 {
2842                         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);
2843                 }
2844                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2845                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2846                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2847                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2848                 {
2849                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2850                         if (rsurface.rtlight)
2851                         {
2852                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2853                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2854                         }
2855                 }
2856                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2857                 if (r_glsl_permutation->loc_Skeletal_Transform12 >= 0 && rsurface.batchskeletalnumtransforms > 0)
2858                         qglUniform4fv(r_glsl_permutation->loc_Skeletal_Transform12, rsurface.batchskeletalnumtransforms*3, rsurface.batchskeletaltransform3x4);
2859                 CHECKGLERROR
2860                 break;
2861         case RENDERPATH_GL11:
2862         case RENDERPATH_GL13:
2863         case RENDERPATH_GLES1:
2864                 break;
2865         case RENDERPATH_SOFT:
2866                 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);
2867                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2868                 R_SetupShader_SetPermutationSoft(mode, permutation);
2869                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2870                 if (mode == SHADERMODE_LIGHTSOURCE)
2871                 {
2872                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2873                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2874                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2875                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2876                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2877                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2878         
2879                         // additive passes are only darkened by fog, not tinted
2880                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2881                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2882                 }
2883                 else
2884                 {
2885                         if (mode == SHADERMODE_FLATCOLOR)
2886                         {
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2888                         }
2889                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2890                         {
2891                                 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]);
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2893                                 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);
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2895                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2896                                 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]);
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2898                         }
2899                         else
2900                         {
2901                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2902                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2903                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2904                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2905                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2906                         }
2907                         // additive passes are only darkened by fog, not tinted
2908                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2909                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2910                         else
2911                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2912                         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);
2913                         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]);
2914                         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]);
2915                         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]);
2916                         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]);
2917                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2918                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2919                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2920                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2921                 }
2922                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2923                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2924                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2925                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2926                 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]);
2927
2928                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2929                 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));
2930                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2931                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2932                 {
2933                         if (rsurface.texture->pantstexture)
2934                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2935                         else
2936                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2937                 }
2938                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2939                 {
2940                         if (rsurface.texture->shirttexture)
2941                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2942                         else
2943                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2944                 }
2945                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2946                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2947                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2948                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2949                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2950                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2951                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2952                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2953                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2954                         );
2955                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2956                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2957                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2958                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2959
2960                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2961                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2962                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2963                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2964                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2965                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2966                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2967                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2968                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2969                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2970                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2971                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2972                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2973                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2974                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2975                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2976                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2977                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2978                 {
2979                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2980                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2981                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2982                 }
2983                 else
2984                 {
2985                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2986                 }
2987 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2988                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2989                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2990                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2991                 {
2992                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2993                         if (rsurface.rtlight)
2994                         {
2995                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2996                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2997                         }
2998                 }
2999                 break;
3000         }
3001 }
3002
3003 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3004 {
3005         // select a permutation of the lighting shader appropriate to this
3006         // combination of texture, entity, light source, and fogging, only use the
3007         // minimum features necessary to avoid wasting rendering time in the
3008         // fragment shader on features that are not being used
3009         unsigned int permutation = 0;
3010         unsigned int mode = 0;
3011         const float *lightcolorbase = rtlight->currentcolor;
3012         float ambientscale = rtlight->ambientscale;
3013         float diffusescale = rtlight->diffusescale;
3014         float specularscale = rtlight->specularscale;
3015         // this is the location of the light in view space
3016         vec3_t viewlightorigin;
3017         // this transforms from view space (camera) to light space (cubemap)
3018         matrix4x4_t viewtolight;
3019         matrix4x4_t lighttoview;
3020         float viewtolight16f[16];
3021         // light source
3022         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3023         if (rtlight->currentcubemap != r_texture_whitecube)
3024                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3025         if (diffusescale > 0)
3026                 permutation |= SHADERPERMUTATION_DIFFUSE;
3027         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3028                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3029         if (r_shadow_usingshadowmap2d)
3030         {
3031                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3032                 if (r_shadow_shadowmapvsdct)
3033                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3034
3035                 if (r_shadow_shadowmap2ddepthbuffer)
3036                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3037         }
3038         if (vid.allowalphatocoverage)
3039                 GL_AlphaToCoverage(false);
3040         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3041         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3042         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3043         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3044         switch(vid.renderpath)
3045         {
3046         case RENDERPATH_D3D9:
3047 #ifdef SUPPORTD3D
3048                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3049                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3050                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3051                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3052                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3053                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3054                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3055                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3056                 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);
3057                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3058                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3059
3060                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3061                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3062                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3063                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3064                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3065 #endif
3066                 break;
3067         case RENDERPATH_D3D10:
3068                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3069                 break;
3070         case RENDERPATH_D3D11:
3071                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3072                 break;
3073         case RENDERPATH_GL20:
3074         case RENDERPATH_GLES2:
3075                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3076                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3077                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3078                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3079                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3080                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3081                 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]);
3082                 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]);
3083                 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);
3084                 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]);
3085                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3086
3087                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3088                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3089                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3090                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3091                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3092                 break;
3093         case RENDERPATH_GL11:
3094         case RENDERPATH_GL13:
3095         case RENDERPATH_GLES1:
3096                 break;
3097         case RENDERPATH_SOFT:
3098                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3099                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3100                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3101                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3102                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3103                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3104                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3105                 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]);
3106                 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);
3107                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3108                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3109
3110                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3111                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3112                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3113                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3114                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3115                 break;
3116         }
3117 }
3118
3119 #define SKINFRAME_HASH 1024
3120
3121 typedef struct
3122 {
3123         int loadsequence; // incremented each level change
3124         memexpandablearray_t array;
3125         skinframe_t *hash[SKINFRAME_HASH];
3126 }
3127 r_skinframe_t;
3128 r_skinframe_t r_skinframe;
3129
3130 void R_SkinFrame_PrepareForPurge(void)
3131 {
3132         r_skinframe.loadsequence++;
3133         // wrap it without hitting zero
3134         if (r_skinframe.loadsequence >= 200)
3135                 r_skinframe.loadsequence = 1;
3136 }
3137
3138 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3139 {
3140         if (!skinframe)
3141                 return;
3142         // mark the skinframe as used for the purging code
3143         skinframe->loadsequence = r_skinframe.loadsequence;
3144 }
3145
3146 void R_SkinFrame_Purge(void)
3147 {
3148         int i;
3149         skinframe_t *s;
3150         for (i = 0;i < SKINFRAME_HASH;i++)
3151         {
3152                 for (s = r_skinframe.hash[i];s;s = s->next)
3153                 {
3154                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3155                         {
3156                                 if (s->merged == s->base)
3157                                         s->merged = NULL;
3158                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3159                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3160                                 R_PurgeTexture(s->merged);s->merged = NULL;
3161                                 R_PurgeTexture(s->base  );s->base   = NULL;
3162                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3163                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3164                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3165                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3166                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3167                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3168                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3169                                 s->loadsequence = 0;
3170                         }
3171                 }
3172         }
3173 }
3174
3175 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3176         skinframe_t *item;
3177         char basename[MAX_QPATH];
3178
3179         Image_StripImageExtension(name, basename, sizeof(basename));
3180
3181         if( last == NULL ) {
3182                 int hashindex;
3183                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3184                 item = r_skinframe.hash[hashindex];
3185         } else {
3186                 item = last->next;
3187         }
3188
3189         // linearly search through the hash bucket
3190         for( ; item ; item = item->next ) {
3191                 if( !strcmp( item->basename, basename ) ) {
3192                         return item;
3193                 }
3194         }
3195         return NULL;
3196 }
3197
3198 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3199 {
3200         skinframe_t *item;
3201         int hashindex;
3202         char basename[MAX_QPATH];
3203
3204         Image_StripImageExtension(name, basename, sizeof(basename));
3205
3206         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3207         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3208                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3209                         break;
3210
3211         if (!item) {
3212                 rtexture_t *dyntexture;
3213                 // check whether its a dynamic texture
3214                 dyntexture = CL_GetDynTexture( basename );
3215                 if (!add && !dyntexture)
3216                         return NULL;
3217                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3218                 memset(item, 0, sizeof(*item));
3219                 strlcpy(item->basename, basename, sizeof(item->basename));
3220                 item->base = dyntexture; // either NULL or dyntexture handle
3221                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3222                 item->comparewidth = comparewidth;
3223                 item->compareheight = compareheight;
3224                 item->comparecrc = comparecrc;
3225                 item->next = r_skinframe.hash[hashindex];
3226                 r_skinframe.hash[hashindex] = item;
3227         }
3228         else if (textureflags & TEXF_FORCE_RELOAD)
3229         {
3230                 rtexture_t *dyntexture;
3231                 // check whether its a dynamic texture
3232                 dyntexture = CL_GetDynTexture( basename );
3233                 if (!add && !dyntexture)
3234                         return NULL;
3235                 if (item->merged == item->base)
3236                         item->merged = NULL;
3237                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3238                 R_PurgeTexture(item->stain );item->stain  = NULL;
3239                 R_PurgeTexture(item->merged);item->merged = NULL;
3240                 R_PurgeTexture(item->base  );item->base   = NULL;
3241                 R_PurgeTexture(item->pants );item->pants  = NULL;
3242                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3243                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3244                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3245                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3246                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3247         R_PurgeTexture(item->reflect);item->reflect = NULL;
3248                 item->loadsequence = 0;
3249         }
3250         else if( item->base == NULL )
3251         {
3252                 rtexture_t *dyntexture;
3253                 // check whether its a dynamic texture
3254                 // 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]
3255                 dyntexture = CL_GetDynTexture( basename );
3256                 item->base = dyntexture; // either NULL or dyntexture handle
3257         }
3258
3259         R_SkinFrame_MarkUsed(item);
3260         return item;
3261 }
3262
3263 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3264         { \
3265                 unsigned long long avgcolor[5], wsum; \
3266                 int pix, comp, w; \
3267                 avgcolor[0] = 0; \
3268                 avgcolor[1] = 0; \
3269                 avgcolor[2] = 0; \
3270                 avgcolor[3] = 0; \
3271                 avgcolor[4] = 0; \
3272                 wsum = 0; \
3273                 for(pix = 0; pix < cnt; ++pix) \
3274                 { \
3275                         w = 0; \
3276                         for(comp = 0; comp < 3; ++comp) \
3277                                 w += getpixel; \
3278                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3279                         { \
3280                                 ++wsum; \
3281                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3282                                 w = getpixel; \
3283                                 for(comp = 0; comp < 3; ++comp) \
3284                                         avgcolor[comp] += getpixel * w; \
3285                                 avgcolor[3] += w; \
3286                         } \
3287                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3288                         avgcolor[4] += getpixel; \
3289                 } \
3290                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3291                         avgcolor[3] = 1; \
3292                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3293                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3294                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3295                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3296         }
3297
3298 extern cvar_t gl_picmip;
3299 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3300 {
3301         int j;
3302         unsigned char *pixels;
3303         unsigned char *bumppixels;
3304         unsigned char *basepixels = NULL;
3305         int basepixels_width = 0;
3306         int basepixels_height = 0;
3307         skinframe_t *skinframe;
3308         rtexture_t *ddsbase = NULL;
3309         qboolean ddshasalpha = false;
3310         float ddsavgcolor[4];
3311         char basename[MAX_QPATH];
3312         int miplevel = R_PicmipForFlags(textureflags);
3313         int savemiplevel = miplevel;
3314         int mymiplevel;
3315         char vabuf[1024];
3316
3317         if (cls.state == ca_dedicated)
3318                 return NULL;
3319
3320         // return an existing skinframe if already loaded
3321         // if loading of the first image fails, don't make a new skinframe as it
3322         // would cause all future lookups of this to be missing
3323         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3324         if (skinframe && skinframe->base)
3325                 return skinframe;
3326
3327         Image_StripImageExtension(name, basename, sizeof(basename));
3328
3329         // check for DDS texture file first
3330         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3331         {
3332                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3333                 if (basepixels == NULL)
3334                         return NULL;
3335         }
3336
3337         // FIXME handle miplevel
3338
3339         if (developer_loading.integer)
3340                 Con_Printf("loading skin \"%s\"\n", name);
3341
3342         // we've got some pixels to store, so really allocate this new texture now
3343         if (!skinframe)
3344                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3345         textureflags &= ~TEXF_FORCE_RELOAD;
3346         skinframe->stain = NULL;
3347         skinframe->merged = NULL;
3348         skinframe->base = NULL;
3349         skinframe->pants = NULL;
3350         skinframe->shirt = NULL;
3351         skinframe->nmap = NULL;
3352         skinframe->gloss = NULL;
3353         skinframe->glow = NULL;
3354         skinframe->fog = NULL;
3355         skinframe->reflect = NULL;
3356         skinframe->hasalpha = false;
3357
3358         if (ddsbase)
3359         {
3360                 skinframe->base = ddsbase;
3361                 skinframe->hasalpha = ddshasalpha;
3362                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3363                 if (r_loadfog && skinframe->hasalpha)
3364                         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);
3365                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3366         }
3367         else
3368         {
3369                 basepixels_width = image_width;
3370                 basepixels_height = image_height;
3371                 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);
3372                 if (textureflags & TEXF_ALPHA)
3373                 {
3374                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3375                         {
3376                                 if (basepixels[j] < 255)
3377                                 {
3378                                         skinframe->hasalpha = true;
3379                                         break;
3380                                 }
3381                         }
3382                         if (r_loadfog && skinframe->hasalpha)
3383                         {
3384                                 // has transparent pixels
3385                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3386                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3387                                 {
3388                                         pixels[j+0] = 255;
3389                                         pixels[j+1] = 255;
3390                                         pixels[j+2] = 255;
3391                                         pixels[j+3] = basepixels[j+3];
3392                                 }
3393                                 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);
3394                                 Mem_Free(pixels);
3395                         }
3396                 }
3397                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3398 #ifndef USE_GLES2
3399                 //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]);
3400                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3401                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3402                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3403                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3404 #endif
3405         }
3406
3407         if (r_loaddds)
3408         {
3409                 mymiplevel = savemiplevel;
3410                 if (r_loadnormalmap)
3411                         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);
3412                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3413                 if (r_loadgloss)
3414                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3415                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3416                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3417                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3418         }
3419
3420         // _norm is the name used by tenebrae and has been adopted as standard
3421         if (r_loadnormalmap && skinframe->nmap == NULL)
3422         {
3423                 mymiplevel = savemiplevel;
3424                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3425                 {
3426                         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);
3427                         Mem_Free(pixels);
3428                         pixels = NULL;
3429                 }
3430                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3431                 {
3432                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3433                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3434                         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);
3435                         Mem_Free(pixels);
3436                         Mem_Free(bumppixels);
3437                 }
3438                 else if (r_shadow_bumpscale_basetexture.value > 0)
3439                 {
3440                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3441                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3442                         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);
3443                         Mem_Free(pixels);
3444                 }
3445 #ifndef USE_GLES2
3446                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3447                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3448 #endif
3449         }
3450
3451         // _luma is supported only for tenebrae compatibility
3452         // _glow is the preferred name
3453         mymiplevel = savemiplevel;
3454         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))))
3455         {
3456                 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);
3457 #ifndef USE_GLES2
3458                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3459                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3460 #endif
3461                 Mem_Free(pixels);pixels = NULL;
3462         }
3463
3464         mymiplevel = savemiplevel;
3465         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3466         {
3467                 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);
3468 #ifndef USE_GLES2
3469                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3470                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3471 #endif
3472                 Mem_Free(pixels);
3473                 pixels = NULL;
3474         }
3475
3476         mymiplevel = savemiplevel;
3477         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3478         {
3479                 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);
3480 #ifndef USE_GLES2
3481                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3482                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3483 #endif
3484                 Mem_Free(pixels);
3485                 pixels = NULL;
3486         }
3487
3488         mymiplevel = savemiplevel;
3489         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3490         {
3491                 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);
3492 #ifndef USE_GLES2
3493                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3494                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3495 #endif
3496                 Mem_Free(pixels);
3497                 pixels = NULL;
3498         }
3499
3500         mymiplevel = savemiplevel;
3501         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3502         {
3503                 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);
3504 #ifndef USE_GLES2
3505                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3506                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3507 #endif
3508                 Mem_Free(pixels);
3509                 pixels = NULL;
3510         }
3511
3512         if (basepixels)
3513                 Mem_Free(basepixels);
3514
3515         return skinframe;
3516 }
3517
3518 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3519 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3520 {
3521         int i;
3522         unsigned char *temp1, *temp2;
3523         skinframe_t *skinframe;
3524         char vabuf[1024];
3525
3526         if (cls.state == ca_dedicated)
3527                 return NULL;
3528
3529         // if already loaded just return it, otherwise make a new skinframe
3530         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3531         if (skinframe->base)
3532                 return skinframe;
3533         textureflags &= ~TEXF_FORCE_RELOAD;
3534
3535         skinframe->stain = NULL;
3536         skinframe->merged = NULL;
3537         skinframe->base = NULL;
3538         skinframe->pants = NULL;
3539         skinframe->shirt = NULL;
3540         skinframe->nmap = NULL;
3541         skinframe->gloss = NULL;
3542         skinframe->glow = NULL;
3543         skinframe->fog = NULL;
3544         skinframe->reflect = NULL;
3545         skinframe->hasalpha = false;
3546
3547         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3548         if (!skindata)
3549                 return NULL;
3550
3551         if (developer_loading.integer)
3552                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3553
3554         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3555         {
3556                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3557                 temp2 = temp1 + width * height * 4;
3558                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3559                 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);
3560                 Mem_Free(temp1);
3561         }
3562         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3563         if (textureflags & TEXF_ALPHA)
3564         {
3565                 for (i = 3;i < width * height * 4;i += 4)
3566                 {
3567                         if (skindata[i] < 255)
3568                         {
3569                                 skinframe->hasalpha = true;
3570                                 break;
3571                         }
3572                 }
3573                 if (r_loadfog && skinframe->hasalpha)
3574                 {
3575                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3576                         memcpy(fogpixels, skindata, width * height * 4);
3577                         for (i = 0;i < width * height * 4;i += 4)
3578                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3579                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3580                         Mem_Free(fogpixels);
3581                 }
3582         }
3583
3584         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3585         //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]);
3586
3587         return skinframe;
3588 }
3589
3590 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3591 {
3592         int i;
3593         int featuresmask;
3594         skinframe_t *skinframe;
3595
3596         if (cls.state == ca_dedicated)
3597                 return NULL;
3598
3599         // if already loaded just return it, otherwise make a new skinframe
3600         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3601         if (skinframe->base)
3602                 return skinframe;
3603         //textureflags &= ~TEXF_FORCE_RELOAD;
3604
3605         skinframe->stain = NULL;
3606         skinframe->merged = NULL;
3607         skinframe->base = NULL;
3608         skinframe->pants = NULL;
3609         skinframe->shirt = NULL;
3610         skinframe->nmap = NULL;
3611         skinframe->gloss = NULL;
3612         skinframe->glow = NULL;
3613         skinframe->fog = NULL;
3614         skinframe->reflect = NULL;
3615         skinframe->hasalpha = false;
3616
3617         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3618         if (!skindata)
3619                 return NULL;
3620
3621         if (developer_loading.integer)
3622                 Con_Printf("loading quake skin \"%s\"\n", name);
3623
3624         // 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)
3625         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3626         memcpy(skinframe->qpixels, skindata, width*height);
3627         skinframe->qwidth = width;
3628         skinframe->qheight = height;
3629
3630         featuresmask = 0;
3631         for (i = 0;i < width * height;i++)
3632                 featuresmask |= palette_featureflags[skindata[i]];
3633
3634         skinframe->hasalpha = false;
3635         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3636         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3637         skinframe->qgeneratemerged = true;
3638         skinframe->qgeneratebase = skinframe->qhascolormapping;
3639         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3640
3641         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3642         //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]);
3643
3644         return skinframe;
3645 }
3646
3647 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3648 {
3649         int width;
3650         int height;
3651         unsigned char *skindata;
3652         char vabuf[1024];
3653
3654         if (!skinframe->qpixels)
3655                 return;
3656
3657         if (!skinframe->qhascolormapping)
3658                 colormapped = false;
3659
3660         if (colormapped)
3661         {
3662                 if (!skinframe->qgeneratebase)
3663                         return;
3664         }
3665         else
3666         {
3667                 if (!skinframe->qgeneratemerged)
3668                         return;
3669         }
3670
3671         width = skinframe->qwidth;
3672         height = skinframe->qheight;
3673         skindata = skinframe->qpixels;
3674
3675         if (skinframe->qgeneratenmap)
3676         {
3677                 unsigned char *temp1, *temp2;
3678                 skinframe->qgeneratenmap = false;
3679                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3680                 temp2 = temp1 + width * height * 4;
3681                 // use either a custom palette or the quake palette
3682                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3683                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3684                 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);
3685                 Mem_Free(temp1);
3686         }
3687
3688         if (skinframe->qgenerateglow)
3689         {
3690                 skinframe->qgenerateglow = false;
3691                 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
3692         }
3693
3694         if (colormapped)
3695         {
3696                 skinframe->qgeneratebase = false;
3697                 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);
3698                 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);
3699                 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);
3700         }
3701         else
3702         {
3703                 skinframe->qgeneratemerged = false;
3704                 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);
3705         }
3706
3707         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3708         {
3709                 Mem_Free(skinframe->qpixels);
3710                 skinframe->qpixels = NULL;
3711         }
3712 }
3713
3714 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)
3715 {
3716         int i;
3717         skinframe_t *skinframe;
3718         char vabuf[1024];
3719
3720         if (cls.state == ca_dedicated)
3721                 return NULL;
3722
3723         // if already loaded just return it, otherwise make a new skinframe
3724         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3725         if (skinframe->base)
3726                 return skinframe;
3727         textureflags &= ~TEXF_FORCE_RELOAD;
3728
3729         skinframe->stain = NULL;
3730         skinframe->merged = NULL;
3731         skinframe->base = NULL;
3732         skinframe->pants = NULL;
3733         skinframe->shirt = NULL;
3734         skinframe->nmap = NULL;
3735         skinframe->gloss = NULL;
3736         skinframe->glow = NULL;
3737         skinframe->fog = NULL;
3738         skinframe->reflect = NULL;
3739         skinframe->hasalpha = false;
3740
3741         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3742         if (!skindata)
3743                 return NULL;
3744
3745         if (developer_loading.integer)
3746                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3747
3748         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3749         if (textureflags & TEXF_ALPHA)
3750         {
3751                 for (i = 0;i < width * height;i++)
3752                 {
3753                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3754                         {
3755                                 skinframe->hasalpha = true;
3756                                 break;
3757                         }
3758                 }
3759                 if (r_loadfog && skinframe->hasalpha)
3760                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3761         }
3762
3763         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3764         //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]);
3765
3766         return skinframe;
3767 }
3768
3769 skinframe_t *R_SkinFrame_LoadMissing(void)
3770 {
3771         skinframe_t *skinframe;
3772
3773         if (cls.state == ca_dedicated)
3774                 return NULL;
3775
3776         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3777         skinframe->stain = NULL;
3778         skinframe->merged = NULL;
3779         skinframe->base = NULL;
3780         skinframe->pants = NULL;
3781         skinframe->shirt = NULL;
3782         skinframe->nmap = NULL;
3783         skinframe->gloss = NULL;
3784         skinframe->glow = NULL;
3785         skinframe->fog = NULL;
3786         skinframe->reflect = NULL;
3787         skinframe->hasalpha = false;
3788
3789         skinframe->avgcolor[0] = rand() / RAND_MAX;
3790         skinframe->avgcolor[1] = rand() / RAND_MAX;
3791         skinframe->avgcolor[2] = rand() / RAND_MAX;
3792         skinframe->avgcolor[3] = 1;
3793
3794         return skinframe;
3795 }
3796
3797 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3798 typedef struct suffixinfo_s
3799 {
3800         const char *suffix;
3801         qboolean flipx, flipy, flipdiagonal;
3802 }
3803 suffixinfo_t;
3804 static suffixinfo_t suffix[3][6] =
3805 {
3806         {
3807                 {"px",   false, false, false},
3808                 {"nx",   false, false, false},
3809                 {"py",   false, false, false},
3810                 {"ny",   false, false, false},
3811                 {"pz",   false, false, false},
3812                 {"nz",   false, false, false}
3813         },
3814         {
3815                 {"posx", false, false, false},
3816                 {"negx", false, false, false},
3817                 {"posy", false, false, false},
3818                 {"negy", false, false, false},
3819                 {"posz", false, false, false},
3820                 {"negz", false, false, false}
3821         },
3822         {
3823                 {"rt",    true, false,  true},
3824                 {"lf",   false,  true,  true},
3825                 {"ft",    true,  true, false},
3826                 {"bk",   false, false, false},
3827                 {"up",    true, false,  true},
3828                 {"dn",    true, false,  true}
3829         }
3830 };
3831
3832 static int componentorder[4] = {0, 1, 2, 3};
3833
3834 static rtexture_t *R_LoadCubemap(const char *basename)
3835 {
3836         int i, j, cubemapsize;
3837         unsigned char *cubemappixels, *image_buffer;
3838         rtexture_t *cubemaptexture;
3839         char name[256];
3840         // must start 0 so the first loadimagepixels has no requested width/height
3841         cubemapsize = 0;
3842         cubemappixels = NULL;
3843         cubemaptexture = NULL;
3844         // keep trying different suffix groups (posx, px, rt) until one loads
3845         for (j = 0;j < 3 && !cubemappixels;j++)
3846         {
3847                 // load the 6 images in the suffix group
3848                 for (i = 0;i < 6;i++)
3849                 {
3850                         // generate an image name based on the base and and suffix
3851                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3852                         // load it
3853                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3854                         {
3855                                 // an image loaded, make sure width and height are equal
3856                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3857                                 {
3858                                         // if this is the first image to load successfully, allocate the cubemap memory
3859                                         if (!cubemappixels && image_width >= 1)
3860                                         {
3861                                                 cubemapsize = image_width;
3862                                                 // note this clears to black, so unavailable sides are black
3863                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3864                                         }
3865                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3866                                         if (cubemappixels)
3867                                                 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);
3868                                 }
3869                                 else
3870                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3871                                 // free the image
3872                                 Mem_Free(image_buffer);
3873                         }
3874                 }
3875         }
3876         // if a cubemap loaded, upload it
3877         if (cubemappixels)
3878         {
3879                 if (developer_loading.integer)
3880                         Con_Printf("loading cubemap \"%s\"\n", basename);
3881
3882                 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);
3883                 Mem_Free(cubemappixels);
3884         }
3885         else
3886         {
3887                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3888                 if (developer_loading.integer)
3889                 {
3890                         Con_Printf("(tried tried images ");
3891                         for (j = 0;j < 3;j++)
3892                                 for (i = 0;i < 6;i++)
3893                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3894                         Con_Print(" and was unable to find any of them).\n");
3895                 }
3896         }
3897         return cubemaptexture;
3898 }
3899
3900 rtexture_t *R_GetCubemap(const char *basename)
3901 {
3902         int i;
3903         for (i = 0;i < r_texture_numcubemaps;i++)
3904                 if (r_texture_cubemaps[i] != NULL)
3905                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3906                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3907         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3908                 return r_texture_whitecube;
3909         r_texture_numcubemaps++;
3910         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3911         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3912         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3913         return r_texture_cubemaps[i]->texture;
3914 }
3915
3916 static void R_Main_FreeViewCache(void)
3917 {
3918         if (r_refdef.viewcache.entityvisible)
3919                 Mem_Free(r_refdef.viewcache.entityvisible);
3920         if (r_refdef.viewcache.world_pvsbits)
3921                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3922         if (r_refdef.viewcache.world_leafvisible)
3923                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3924         if (r_refdef.viewcache.world_surfacevisible)
3925                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3926         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3927 }
3928
3929 static void R_Main_ResizeViewCache(void)
3930 {
3931         int numentities = r_refdef.scene.numentities;
3932         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3933         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3934         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3935         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3936         if (r_refdef.viewcache.maxentities < numentities)
3937         {
3938                 r_refdef.viewcache.maxentities = numentities;
3939                 if (r_refdef.viewcache.entityvisible)
3940                         Mem_Free(r_refdef.viewcache.entityvisible);
3941                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3942         }
3943         if (r_refdef.viewcache.world_numclusters != numclusters)
3944         {
3945                 r_refdef.viewcache.world_numclusters = numclusters;
3946                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3947                 if (r_refdef.viewcache.world_pvsbits)
3948                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3949                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3950         }
3951         if (r_refdef.viewcache.world_numleafs != numleafs)
3952         {
3953                 r_refdef.viewcache.world_numleafs = numleafs;
3954                 if (r_refdef.viewcache.world_leafvisible)
3955                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3956                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3957         }
3958         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3959         {
3960                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3961                 if (r_refdef.viewcache.world_surfacevisible)
3962                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3963                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3964         }
3965 }
3966
3967 extern rtexture_t *loadingscreentexture;
3968 static void gl_main_start(void)
3969 {
3970         loadingscreentexture = NULL;
3971         r_texture_blanknormalmap = NULL;
3972         r_texture_white = NULL;
3973         r_texture_grey128 = NULL;
3974         r_texture_black = NULL;
3975         r_texture_whitecube = NULL;
3976         r_texture_normalizationcube = NULL;
3977         r_texture_fogattenuation = NULL;
3978         r_texture_fogheighttexture = NULL;
3979         r_texture_gammaramps = NULL;
3980         r_texture_numcubemaps = 0;
3981
3982         r_loaddds = r_texture_dds_load.integer != 0;
3983         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3984
3985         switch(vid.renderpath)
3986         {
3987         case RENDERPATH_GL20:
3988         case RENDERPATH_D3D9:
3989         case RENDERPATH_D3D10:
3990         case RENDERPATH_D3D11:
3991         case RENDERPATH_SOFT:
3992         case RENDERPATH_GLES2:
3993                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3994                 Cvar_SetValueQuick(&gl_combine, 1);
3995                 Cvar_SetValueQuick(&r_glsl, 1);
3996                 r_loadnormalmap = true;
3997                 r_loadgloss = true;
3998                 r_loadfog = false;
3999                 break;
4000         case RENDERPATH_GL13:
4001         case RENDERPATH_GLES1:
4002                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4003                 Cvar_SetValueQuick(&gl_combine, 1);
4004                 Cvar_SetValueQuick(&r_glsl, 0);
4005                 r_loadnormalmap = false;
4006                 r_loadgloss = false;
4007                 r_loadfog = true;
4008                 break;
4009         case RENDERPATH_GL11:
4010                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4011                 Cvar_SetValueQuick(&gl_combine, 0);
4012                 Cvar_SetValueQuick(&r_glsl, 0);
4013                 r_loadnormalmap = false;
4014                 r_loadgloss = false;
4015                 r_loadfog = true;
4016                 break;
4017         }
4018
4019         R_AnimCache_Free();
4020         R_FrameData_Reset();
4021
4022         r_numqueries = 0;
4023         r_maxqueries = 0;
4024         memset(r_queries, 0, sizeof(r_queries));
4025
4026         r_qwskincache = NULL;
4027         r_qwskincache_size = 0;
4028
4029         // due to caching of texture_t references, the collision cache must be reset
4030         Collision_Cache_Reset(true);
4031
4032         // set up r_skinframe loading system for textures
4033         memset(&r_skinframe, 0, sizeof(r_skinframe));
4034         r_skinframe.loadsequence = 1;
4035         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4036
4037         r_main_texturepool = R_AllocTexturePool();
4038         R_BuildBlankTextures();
4039         R_BuildNoTexture();
4040         if (vid.support.arb_texture_cube_map)
4041         {
4042                 R_BuildWhiteCube();
4043                 R_BuildNormalizationCube();
4044         }
4045         r_texture_fogattenuation = NULL;
4046         r_texture_fogheighttexture = NULL;
4047         r_texture_gammaramps = NULL;
4048         //r_texture_fogintensity = NULL;
4049         memset(&r_fb, 0, sizeof(r_fb));
4050         r_glsl_permutation = NULL;
4051         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4052         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4053         glslshaderstring = NULL;
4054 #ifdef SUPPORTD3D
4055         r_hlsl_permutation = NULL;
4056         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4057         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4058 #endif
4059         hlslshaderstring = NULL;
4060         memset(&r_svbsp, 0, sizeof (r_svbsp));
4061
4062         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4063         r_texture_numcubemaps = 0;
4064
4065         r_refdef.fogmasktable_density = 0;
4066 }
4067
4068 static void gl_main_shutdown(void)
4069 {
4070         R_AnimCache_Free();
4071         R_FrameData_Reset();
4072
4073         R_Main_FreeViewCache();
4074
4075         switch(vid.renderpath)
4076         {
4077         case RENDERPATH_GL11:
4078         case RENDERPATH_GL13:
4079         case RENDERPATH_GL20:
4080         case RENDERPATH_GLES1:
4081         case RENDERPATH_GLES2:
4082 #ifdef GL_SAMPLES_PASSED_ARB
4083                 if (r_maxqueries)
4084                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4085 #endif
4086                 break;
4087         case RENDERPATH_D3D9:
4088                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4089                 break;
4090         case RENDERPATH_D3D10:
4091                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4092                 break;
4093         case RENDERPATH_D3D11:
4094                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4095                 break;
4096         case RENDERPATH_SOFT:
4097                 break;
4098         }
4099
4100         r_numqueries = 0;
4101         r_maxqueries = 0;
4102         memset(r_queries, 0, sizeof(r_queries));
4103
4104         r_qwskincache = NULL;
4105         r_qwskincache_size = 0;
4106
4107         // clear out the r_skinframe state
4108         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4109         memset(&r_skinframe, 0, sizeof(r_skinframe));
4110
4111         if (r_svbsp.nodes)
4112                 Mem_Free(r_svbsp.nodes);
4113         memset(&r_svbsp, 0, sizeof (r_svbsp));
4114         R_FreeTexturePool(&r_main_texturepool);
4115         loadingscreentexture = NULL;
4116         r_texture_blanknormalmap = NULL;
4117         r_texture_white = NULL;
4118         r_texture_grey128 = NULL;
4119         r_texture_black = NULL;
4120         r_texture_whitecube = NULL;
4121         r_texture_normalizationcube = NULL;
4122         r_texture_fogattenuation = NULL;
4123         r_texture_fogheighttexture = NULL;
4124         r_texture_gammaramps = NULL;
4125         r_texture_numcubemaps = 0;
4126         //r_texture_fogintensity = NULL;
4127         memset(&r_fb, 0, sizeof(r_fb));
4128         R_GLSL_Restart_f();
4129
4130         r_glsl_permutation = NULL;
4131         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4132         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4133         glslshaderstring = NULL;
4134 #ifdef SUPPORTD3D
4135         r_hlsl_permutation = NULL;
4136         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4137         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4138 #endif
4139         hlslshaderstring = NULL;
4140 }
4141
4142 static void gl_main_newmap(void)
4143 {
4144         // FIXME: move this code to client
4145         char *entities, entname[MAX_QPATH];
4146         if (r_qwskincache)
4147                 Mem_Free(r_qwskincache);
4148         r_qwskincache = NULL;
4149         r_qwskincache_size = 0;
4150         if (cl.worldmodel)
4151         {
4152                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4153                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4154                 {
4155                         CL_ParseEntityLump(entities);
4156                         Mem_Free(entities);
4157                         return;
4158                 }
4159                 if (cl.worldmodel->brush.entities)
4160                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4161         }
4162         R_Main_FreeViewCache();
4163
4164         R_FrameData_Reset();
4165 }
4166
4167 void GL_Main_Init(void)
4168 {
4169         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4170
4171         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4172         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4173         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4174         if (gamemode == GAME_NEHAHRA)
4175         {
4176                 Cvar_RegisterVariable (&gl_fogenable);
4177                 Cvar_RegisterVariable (&gl_fogdensity);
4178                 Cvar_RegisterVariable (&gl_fogred);
4179                 Cvar_RegisterVariable (&gl_foggreen);
4180                 Cvar_RegisterVariable (&gl_fogblue);
4181                 Cvar_RegisterVariable (&gl_fogstart);
4182                 Cvar_RegisterVariable (&gl_fogend);
4183                 Cvar_RegisterVariable (&gl_skyclip);
4184         }
4185         Cvar_RegisterVariable(&r_motionblur);
4186         Cvar_RegisterVariable(&r_damageblur);
4187         Cvar_RegisterVariable(&r_motionblur_averaging);
4188         Cvar_RegisterVariable(&r_motionblur_randomize);
4189         Cvar_RegisterVariable(&r_motionblur_minblur);
4190         Cvar_RegisterVariable(&r_motionblur_maxblur);
4191         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4192         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4193         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4194         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4195         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4196         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4197         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4198         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4199         Cvar_RegisterVariable(&r_equalize_entities_by);
4200         Cvar_RegisterVariable(&r_equalize_entities_to);
4201         Cvar_RegisterVariable(&r_depthfirst);
4202         Cvar_RegisterVariable(&r_useinfinitefarclip);
4203         Cvar_RegisterVariable(&r_farclip_base);
4204         Cvar_RegisterVariable(&r_farclip_world);
4205         Cvar_RegisterVariable(&r_nearclip);
4206         Cvar_RegisterVariable(&r_deformvertexes);
4207         Cvar_RegisterVariable(&r_transparent);
4208         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4209         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4210         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4211         Cvar_RegisterVariable(&r_showoverdraw);
4212         Cvar_RegisterVariable(&r_showbboxes);
4213         Cvar_RegisterVariable(&r_showsurfaces);
4214         Cvar_RegisterVariable(&r_showtris);
4215         Cvar_RegisterVariable(&r_shownormals);
4216         Cvar_RegisterVariable(&r_showlighting);
4217         Cvar_RegisterVariable(&r_showshadowvolumes);
4218         Cvar_RegisterVariable(&r_showcollisionbrushes);
4219         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4220         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4221         Cvar_RegisterVariable(&r_showdisabledepthtest);
4222         Cvar_RegisterVariable(&r_drawportals);
4223         Cvar_RegisterVariable(&r_drawentities);
4224         Cvar_RegisterVariable(&r_draw2d);
4225         Cvar_RegisterVariable(&r_drawworld);
4226         Cvar_RegisterVariable(&r_cullentities_trace);
4227         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4228         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4229         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4230         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4231         Cvar_RegisterVariable(&r_sortentities);
4232         Cvar_RegisterVariable(&r_drawviewmodel);
4233         Cvar_RegisterVariable(&r_drawexteriormodel);
4234         Cvar_RegisterVariable(&r_speeds);
4235         Cvar_RegisterVariable(&r_fullbrights);
4236         Cvar_RegisterVariable(&r_wateralpha);
4237         Cvar_RegisterVariable(&r_dynamic);
4238         Cvar_RegisterVariable(&r_fakelight);
4239         Cvar_RegisterVariable(&r_fakelight_intensity);
4240         Cvar_RegisterVariable(&r_fullbright);
4241         Cvar_RegisterVariable(&r_shadows);
4242         Cvar_RegisterVariable(&r_shadows_darken);
4243         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4244         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4245         Cvar_RegisterVariable(&r_shadows_throwdistance);
4246         Cvar_RegisterVariable(&r_shadows_throwdirection);
4247         Cvar_RegisterVariable(&r_shadows_focus);
4248         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4249         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4250         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4251         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4252         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4253         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4254         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4255         Cvar_RegisterVariable(&r_fog_exp2);
4256         Cvar_RegisterVariable(&r_fog_clear);
4257         Cvar_RegisterVariable(&r_drawfog);
4258         Cvar_RegisterVariable(&r_transparentdepthmasking);
4259         Cvar_RegisterVariable(&r_transparent_sortmindist);
4260         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4261         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4262         Cvar_RegisterVariable(&r_texture_dds_load);
4263         Cvar_RegisterVariable(&r_texture_dds_save);
4264         Cvar_RegisterVariable(&r_textureunits);
4265         Cvar_RegisterVariable(&gl_combine);
4266         Cvar_RegisterVariable(&r_usedepthtextures);
4267         Cvar_RegisterVariable(&r_viewfbo);
4268         Cvar_RegisterVariable(&r_viewscale);
4269         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4270         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4271         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4272         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4273         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4274         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4275         Cvar_RegisterVariable(&r_glsl);
4276         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4277         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4278         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4279         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4280         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4281         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4282         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4283         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4284         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4285         Cvar_RegisterVariable(&r_glsl_postprocess);
4286         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4287         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4288         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4289         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4290         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4291         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4292         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4293         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4294         Cvar_RegisterVariable(&r_celshading);
4295         Cvar_RegisterVariable(&r_celoutlines);
4296
4297         Cvar_RegisterVariable(&r_water);
4298         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4299         Cvar_RegisterVariable(&r_water_clippingplanebias);
4300         Cvar_RegisterVariable(&r_water_refractdistort);
4301         Cvar_RegisterVariable(&r_water_reflectdistort);
4302         Cvar_RegisterVariable(&r_water_scissormode);
4303         Cvar_RegisterVariable(&r_water_lowquality);
4304         Cvar_RegisterVariable(&r_water_hideplayer);
4305         Cvar_RegisterVariable(&r_water_fbo);
4306
4307         Cvar_RegisterVariable(&r_lerpsprites);
4308         Cvar_RegisterVariable(&r_lerpmodels);
4309         Cvar_RegisterVariable(&r_lerplightstyles);
4310         Cvar_RegisterVariable(&r_waterscroll);
4311         Cvar_RegisterVariable(&r_bloom);
4312         Cvar_RegisterVariable(&r_bloom_colorscale);
4313         Cvar_RegisterVariable(&r_bloom_brighten);
4314         Cvar_RegisterVariable(&r_bloom_blur);
4315         Cvar_RegisterVariable(&r_bloom_resolution);
4316         Cvar_RegisterVariable(&r_bloom_colorexponent);
4317         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4318         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4319         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4320         Cvar_RegisterVariable(&r_hdr_glowintensity);
4321         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4322         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4323         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4324         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4325         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4326         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4327         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4328         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4329         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4330         Cvar_RegisterVariable(&developer_texturelogging);
4331         Cvar_RegisterVariable(&gl_lightmaps);
4332         Cvar_RegisterVariable(&r_test);
4333         Cvar_RegisterVariable(&r_batch_multidraw);
4334         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4335         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4336         Cvar_RegisterVariable(&r_glsl_skeletal);
4337         Cvar_RegisterVariable(&r_glsl_saturation);
4338         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4339         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4340         Cvar_RegisterVariable(&r_framedatasize);
4341         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4342                 Cvar_SetValue("r_fullbrights", 0);
4343         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4344 }
4345
4346 void Render_Init(void)
4347 {
4348         gl_backend_init();
4349         R_Textures_Init();
4350         GL_Main_Init();
4351         Font_Init();
4352         GL_Draw_Init();
4353         R_Shadow_Init();
4354         R_Sky_Init();
4355         GL_Surf_Init();
4356         Sbar_Init();
4357         R_Particles_Init();
4358         R_Explosion_Init();
4359         R_LightningBeams_Init();
4360         Mod_RenderInit();
4361 }
4362
4363 /*
4364 ===============
4365 GL_Init
4366 ===============
4367 */
4368 #ifndef USE_GLES2
4369 extern char *ENGINE_EXTENSIONS;
4370 void GL_Init (void)
4371 {
4372         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4373         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4374         gl_version = (const char *)qglGetString(GL_VERSION);
4375         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4376
4377         if (!gl_extensions)
4378                 gl_extensions = "";
4379         if (!gl_platformextensions)
4380                 gl_platformextensions = "";
4381
4382         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4383         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4384         Con_Printf("GL_VERSION: %s\n", gl_version);
4385         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4386         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4387
4388         VID_CheckExtensions();
4389
4390         // LordHavoc: report supported extensions
4391         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4392
4393         // clear to black (loading plaque will be seen over this)
4394         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4395 }
4396 #endif
4397
4398 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4399 {
4400         int i;
4401         mplane_t *p;
4402         if (r_trippy.integer)
4403                 return false;
4404         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4405         {
4406                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4407                 if (i == 4)
4408                         continue;
4409                 p = r_refdef.view.frustum + i;
4410                 switch(p->signbits)
4411                 {
4412                 default:
4413                 case 0:
4414                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4415                                 return true;
4416                         break;
4417                 case 1:
4418                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4419                                 return true;
4420                         break;
4421                 case 2:
4422                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4423                                 return true;
4424                         break;
4425                 case 3:
4426                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4427                                 return true;
4428                         break;
4429                 case 4:
4430                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4431                                 return true;
4432                         break;
4433                 case 5:
4434                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4435                                 return true;
4436                         break;
4437                 case 6:
4438                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4439                                 return true;
4440                         break;
4441                 case 7:
4442                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 }
4446         }
4447         return false;
4448 }
4449
4450 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4451 {
4452         int i;
4453         const mplane_t *p;
4454         if (r_trippy.integer)
4455                 return false;
4456         for (i = 0;i < numplanes;i++)
4457         {
4458                 p = planes + i;
4459                 switch(p->signbits)
4460                 {
4461                 default:
4462                 case 0:
4463                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4464                                 return true;
4465                         break;
4466                 case 1:
4467                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4468                                 return true;
4469                         break;
4470                 case 2:
4471                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4472                                 return true;
4473                         break;
4474                 case 3:
4475                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4476                                 return true;
4477                         break;
4478                 case 4:
4479                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4480                                 return true;
4481                         break;
4482                 case 5:
4483                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4484                                 return true;
4485                         break;
4486                 case 6:
4487                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4488                                 return true;
4489                         break;
4490                 case 7:
4491                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4492                                 return true;
4493                         break;
4494                 }
4495         }
4496         return false;
4497 }
4498
4499 //==================================================================================
4500
4501 // LordHavoc: this stores temporary data used within the same frame
4502
4503 typedef struct r_framedata_mem_s
4504 {
4505         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4506         size_t size; // how much usable space
4507         size_t current; // how much space in use
4508         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4509         size_t wantedsize; // how much space was allocated
4510         unsigned char *data; // start of real data (16byte aligned)
4511 }
4512 r_framedata_mem_t;
4513
4514 static r_framedata_mem_t *r_framedata_mem;
4515
4516 void R_FrameData_Reset(void)
4517 {
4518         while (r_framedata_mem)
4519         {
4520                 r_framedata_mem_t *next = r_framedata_mem->purge;
4521                 Mem_Free(r_framedata_mem);
4522                 r_framedata_mem = next;
4523         }
4524 }
4525
4526 static void R_FrameData_Resize(void)
4527 {
4528         size_t wantedsize;
4529         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4530         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4531         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4532         {
4533                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4534                 newmem->wantedsize = wantedsize;
4535                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4536                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4537                 newmem->current = 0;
4538                 newmem->mark = 0;
4539                 newmem->purge = r_framedata_mem;
4540                 r_framedata_mem = newmem;
4541         }
4542 }
4543
4544 void R_FrameData_NewFrame(void)
4545 {
4546         R_FrameData_Resize();
4547         if (!r_framedata_mem)
4548                 return;
4549         // if we ran out of space on the last frame, free the old memory now
4550         while (r_framedata_mem->purge)
4551         {
4552                 // repeatedly remove the second item in the list, leaving only head
4553                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4554                 Mem_Free(r_framedata_mem->purge);
4555                 r_framedata_mem->purge = next;
4556         }
4557         // reset the current mem pointer
4558         r_framedata_mem->current = 0;
4559         r_framedata_mem->mark = 0;
4560 }
4561
4562 void *R_FrameData_Alloc(size_t size)
4563 {
4564         void *data;
4565
4566         // align to 16 byte boundary - the data pointer is already aligned, so we
4567         // only need to ensure the size of every allocation is also aligned
4568         size = (size + 15) & ~15;
4569
4570         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4571         {
4572                 // emergency - we ran out of space, allocate more memory
4573                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4574                 R_FrameData_Resize();
4575         }
4576
4577         data = r_framedata_mem->data + r_framedata_mem->current;
4578         r_framedata_mem->current += size;
4579
4580         // count the usage for stats
4581         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4582         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4583
4584         return (void *)data;
4585 }
4586
4587 void *R_FrameData_Store(size_t size, void *data)
4588 {
4589         void *d = R_FrameData_Alloc(size);
4590         if (d && data)
4591                 memcpy(d, data, size);
4592         return d;
4593 }
4594
4595 void R_FrameData_SetMark(void)
4596 {
4597         if (!r_framedata_mem)
4598                 return;
4599         r_framedata_mem->mark = r_framedata_mem->current;
4600 }
4601
4602 void R_FrameData_ReturnToMark(void)
4603 {
4604         if (!r_framedata_mem)
4605                 return;
4606         r_framedata_mem->current = r_framedata_mem->mark;
4607 }
4608
4609 //==================================================================================
4610
4611 // LordHavoc: animcache originally written by Echon, rewritten since then
4612
4613 /**
4614  * Animation cache prevents re-generating mesh data for an animated model
4615  * multiple times in one frame for lighting, shadowing, reflections, etc.
4616  */
4617
4618 void R_AnimCache_Free(void)
4619 {
4620 }
4621
4622 void R_AnimCache_ClearCache(void)
4623 {
4624         int i;
4625         entity_render_t *ent;
4626
4627         for (i = 0;i < r_refdef.scene.numentities;i++)
4628         {
4629                 ent = r_refdef.scene.entities[i];
4630                 ent->animcache_vertex3f = NULL;
4631                 ent->animcache_normal3f = NULL;
4632                 ent->animcache_svector3f = NULL;
4633                 ent->animcache_tvector3f = NULL;
4634                 ent->animcache_vertexmesh = NULL;
4635                 ent->animcache_vertex3fbuffer = NULL;
4636                 ent->animcache_vertexmeshbuffer = NULL;
4637                 ent->animcache_skeletaltransform3x4 = NULL;
4638         }
4639 }
4640
4641 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4642 {
4643         int i;
4644
4645         // check if we need the meshbuffers
4646         if (!vid.useinterleavedarrays)
4647                 return;
4648
4649         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4650                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4651         // TODO: upload vertex3f buffer?
4652         if (ent->animcache_vertexmesh)
4653         {
4654                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4655                 for (i = 0;i < numvertices;i++)
4656                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4657                 if (ent->animcache_svector3f)
4658                         for (i = 0;i < numvertices;i++)
4659                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4660                 if (ent->animcache_tvector3f)
4661                         for (i = 0;i < numvertices;i++)
4662                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4663                 if (ent->animcache_normal3f)
4664                         for (i = 0;i < numvertices;i++)
4665                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4666                 // TODO: upload vertexmeshbuffer?
4667         }
4668 }
4669
4670 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4671 {
4672         dp_model_t *model = ent->model;
4673         int numvertices;
4674
4675         // cache skeletal animation data first (primarily for gpu-skinning)
4676         if (!ent->animcache_skeletaltransform3x4 && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4677         {
4678                 int i;
4679                 int blends;
4680                 const skeleton_t *skeleton = ent->skeleton;
4681                 const frameblend_t *frameblend = ent->frameblend;
4682                 float *boneposerelative;
4683                 float m[12];
4684                 static float bonepose[256][12];
4685                 ent->animcache_skeletaltransform3x4 = R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4686                 boneposerelative = ent->animcache_skeletaltransform3x4;
4687                 if (skeleton && !skeleton->relativetransforms)
4688                         skeleton = NULL;
4689                 // resolve hierarchy and make relative transforms (deforms) which the shader wants
4690                 if (skeleton)
4691                 {
4692                         for (i = 0;i < model->num_bones;i++)
4693                         {
4694                                 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
4695                                 if (model->data_bones[i].parent >= 0)
4696                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4697                                 else
4698                                         memcpy(bonepose[i], m, sizeof(m));
4699
4700                                 // create a relative deformation matrix to describe displacement
4701                                 // from the base mesh, which is used by the actual weighting
4702                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4703                         }
4704                 }
4705                 else
4706                 {
4707                         for (i = 0;i < model->num_bones;i++)
4708                         {
4709                                 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
4710                                 float lerp = frameblend[0].lerp,
4711                                         tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4712                                         rx = pose7s[3] * lerp,
4713                                         ry = pose7s[4] * lerp,
4714                                         rz = pose7s[5] * lerp,
4715                                         rw = pose7s[6] * lerp,
4716                                         dx = tx*rw + ty*rz - tz*ry,
4717                                         dy = -tx*rz + ty*rw + tz*rx,
4718                                         dz = tx*ry - ty*rx + tz*rw,
4719                                         dw = -tx*rx - ty*ry - tz*rz,
4720                                         scale, sx, sy, sz, sw;
4721                                 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
4722                                 {
4723                                         const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
4724                                         float lerp = frameblend[blends].lerp,
4725                                                 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4726                                                 qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
4727                                         if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
4728                                         qx *= lerp;
4729                                         qy *= lerp;
4730                                         qz *= lerp;
4731                                         qw *= lerp;
4732                                         rx += qx;
4733                                         ry += qy;
4734                                         rz += qz;
4735                                         rw += qw;
4736                                         dx += tx*qw + ty*qz - tz*qy;
4737                                         dy += -tx*qz + ty*qw + tz*qx;
4738                                         dz += tx*qy - ty*qx + tz*qw;
4739                                         dw += -tx*qx - ty*qy - tz*qz;
4740                                 }
4741                                 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
4742                                 sx = rx * scale;
4743                                 sy = ry * scale;
4744                                 sz = rz * scale;
4745                                 sw = rw * scale;
4746                                 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
4747                                 m[1] = 2*(sx*ry - sw*rz);
4748                                 m[2] = 2*(sx*rz + sw*ry);
4749                                 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
4750                                 m[4] = 2*(sx*ry + sw*rz);
4751                                 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
4752                                 m[6] = 2*(sy*rz - sw*rx);
4753                                 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
4754                                 m[8] = 2*(sx*rz - sw*ry);
4755                                 m[9] = 2*(sy*rz + sw*rx);
4756                                 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
4757                                 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
4758                                 if (i == r_skeletal_debugbone.integer)
4759                                         m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
4760                                 m[3] *= r_skeletal_debugtranslatex.value;
4761                                 m[7] *= r_skeletal_debugtranslatey.value;
4762                                 m[11] *= r_skeletal_debugtranslatez.value;
4763                                 if (model->data_bones[i].parent >= 0)
4764                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4765                                 else
4766                                         memcpy(bonepose[i], m, sizeof(m));
4767                                 // create a relative deformation matrix to describe displacement
4768                                 // from the base mesh, which is used by the actual weighting
4769                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4770                         }
4771                 }
4772         }
4773
4774         // see if it's already cached this frame
4775         if (ent->animcache_vertex3f)
4776         {
4777                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4778                 if (wantnormals || wanttangents)
4779                 {
4780                         if (ent->animcache_normal3f)
4781                                 wantnormals = false;
4782                         if (ent->animcache_svector3f)
4783                                 wanttangents = false;
4784                         if (wantnormals || wanttangents)
4785                         {
4786                                 numvertices = model->surfmesh.num_vertices;
4787                                 if (wantnormals)
4788                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4789                                 if (wanttangents)
4790                                 {
4791                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4792                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4793                                 }
4794                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4795                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4796                         }
4797                 }
4798         }
4799         else
4800         {
4801                 // see if this ent is worth caching
4802                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4803                         return false;
4804                 // skip entity if the shader backend has a cheaper way
4805                 if (model->surfmesh.data_skeletalindex4ub && r_glsl_skeletal.integer)
4806                 {
4807                         switch (vid.renderpath)
4808                         {
4809                         case RENDERPATH_GL20:
4810                                 return false;
4811                         case RENDERPATH_GL11:
4812                         case RENDERPATH_GL13:
4813                         case RENDERPATH_GLES1:
4814                         case RENDERPATH_GLES2:
4815                         case RENDERPATH_D3D9:
4816                         case RENDERPATH_D3D10:
4817                         case RENDERPATH_D3D11:
4818                         case RENDERPATH_SOFT:
4819                                 break;
4820                         }
4821                 }
4822                 // get some memory for this entity and generate mesh data
4823                 numvertices = model->surfmesh.num_vertices;
4824                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4825                 if (wantnormals)
4826                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4827                 if (wanttangents)
4828                 {
4829                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4830                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4831                 }
4832                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4833                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4834         }
4835         return true;
4836 }
4837
4838 void R_AnimCache_CacheVisibleEntities(void)
4839 {
4840         int i;
4841         qboolean wantnormals = true;
4842         qboolean wanttangents = !r_showsurfaces.integer;
4843
4844         switch(vid.renderpath)
4845         {
4846         case RENDERPATH_GL20:
4847         case RENDERPATH_D3D9:
4848         case RENDERPATH_D3D10:
4849         case RENDERPATH_D3D11:
4850         case RENDERPATH_GLES2:
4851                 break;
4852         case RENDERPATH_GL11:
4853         case RENDERPATH_GL13:
4854         case RENDERPATH_GLES1:
4855                 wanttangents = false;
4856                 break;
4857         case RENDERPATH_SOFT:
4858                 break;
4859         }
4860
4861         if (r_shownormals.integer)
4862                 wanttangents = wantnormals = true;
4863
4864         // TODO: thread this
4865         // NOTE: R_PrepareRTLights() also caches entities
4866
4867         for (i = 0;i < r_refdef.scene.numentities;i++)
4868                 if (r_refdef.viewcache.entityvisible[i])
4869                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4870 }
4871
4872 //==================================================================================
4873
4874 extern cvar_t r_overheadsprites_pushback;
4875
4876 static void R_View_UpdateEntityLighting (void)
4877 {
4878         int i;
4879         entity_render_t *ent;
4880         vec3_t tempdiffusenormal, avg;
4881         vec_t f, fa, fd, fdd;
4882         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4883
4884         for (i = 0;i < r_refdef.scene.numentities;i++)
4885         {
4886                 ent = r_refdef.scene.entities[i];
4887
4888                 // skip unseen models
4889                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4890                         continue;
4891
4892                 // skip bsp models
4893                 if (ent->model && ent->model == cl.worldmodel)
4894                 {
4895                         // TODO: use modellight for r_ambient settings on world?
4896                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4897                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4898                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4899                         continue;
4900                 }
4901                 
4902                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4903                 {
4904                         // aleady updated by CSQC
4905                         // TODO: force modellight on BSP models in this case?
4906                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4907                 }
4908                 else
4909                 {
4910                         // fetch the lighting from the worldmodel data
4911                         VectorClear(ent->modellight_ambient);
4912                         VectorClear(ent->modellight_diffuse);
4913                         VectorClear(tempdiffusenormal);
4914                         if (ent->flags & RENDER_LIGHT)
4915                         {
4916                                 vec3_t org;
4917                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4918
4919                                 // complete lightning for lit sprites
4920                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4921                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4922                                 {
4923                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4924                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4925                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4926                                 }
4927                                 else
4928                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4929
4930                                 if(ent->flags & RENDER_EQUALIZE)
4931                                 {
4932                                         // first fix up ambient lighting...
4933                                         if(r_equalize_entities_minambient.value > 0)
4934                                         {
4935                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4936                                                 if(fd > 0)
4937                                                 {
4938                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4939                                                         if(fa < r_equalize_entities_minambient.value * fd)
4940                                                         {
4941                                                                 // solve:
4942                                                                 //   fa'/fd' = minambient
4943                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4944                                                                 //   ...
4945                                                                 //   fa' = fd' * minambient
4946                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4947                                                                 //   ...
4948                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4949                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4950                                                                 //   ...
4951                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4952                                                                 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
4953                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4954                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4955                                                         }
4956                                                 }
4957                                         }
4958
4959                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4960                                         {
4961                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4962                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4963                                                 f = fa + 0.25 * fd;
4964                                                 if(f > 0)
4965                                                 {
4966                                                         // adjust brightness and saturation to target
4967                                                         avg[0] = avg[1] = avg[2] = fa / f;
4968                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4969                                                         avg[0] = avg[1] = avg[2] = fd / f;
4970                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4971                                                 }
4972                                         }
4973                                 }
4974                         }
4975                         else // highly rare
4976                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4977                 }
4978
4979                 // move the light direction into modelspace coordinates for lighting code
4980                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4981                 if(VectorLength2(ent->modellight_lightdir) == 0)
4982                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4983                 VectorNormalize(ent->modellight_lightdir);
4984         }
4985 }
4986
4987 #define MAX_LINEOFSIGHTTRACES 64
4988
4989 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4990 {
4991         int i;
4992         vec3_t boxmins, boxmaxs;
4993         vec3_t start;
4994         vec3_t end;
4995         dp_model_t *model = r_refdef.scene.worldmodel;
4996
4997         if (!model || !model->brush.TraceLineOfSight)
4998                 return true;
4999
5000         // expand the box a little
5001         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5002         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5003         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5004         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5005         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5006         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5007
5008         // return true if eye is inside enlarged box
5009         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5010                 return true;
5011
5012         // try center
5013         VectorCopy(eye, start);
5014         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5015         if (model->brush.TraceLineOfSight(model, start, end))
5016                 return true;
5017
5018         // try various random positions
5019         for (i = 0;i < numsamples;i++)
5020         {
5021                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5022                 if (model->brush.TraceLineOfSight(model, start, end))
5023                         return true;
5024         }
5025
5026         return false;
5027 }
5028
5029
5030 static void R_View_UpdateEntityVisible (void)
5031 {
5032         int i;
5033         int renderimask;
5034         int samples;
5035         entity_render_t *ent;
5036
5037         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5038                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5039                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5040                 :                                                          RENDER_EXTERIORMODEL;
5041         if (!r_drawviewmodel.integer)
5042                 renderimask |= RENDER_VIEWMODEL;
5043         if (!r_drawexteriormodel.integer)
5044                 renderimask |= RENDER_EXTERIORMODEL;
5045         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5046         {
5047                 // worldmodel can check visibility
5048                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5049                 for (i = 0;i < r_refdef.scene.numentities;i++)
5050                 {
5051                         ent = r_refdef.scene.entities[i];
5052                         if (!(ent->flags & renderimask))
5053                         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)))
5054                         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))
5055                                 r_refdef.viewcache.entityvisible[i] = true;
5056                 }
5057         }
5058         else
5059         {
5060                 // no worldmodel or it can't check visibility
5061                 for (i = 0;i < r_refdef.scene.numentities;i++)
5062                 {
5063                         ent = r_refdef.scene.entities[i];
5064                         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));
5065                 }
5066         }
5067         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5068                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5069         {
5070                 for (i = 0;i < r_refdef.scene.numentities;i++)
5071                 {
5072                         if (!r_refdef.viewcache.entityvisible[i])
5073                                 continue;
5074                         ent = r_refdef.scene.entities[i];
5075                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5076                         {
5077                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5078                                 if (samples < 0)
5079                                         continue; // temp entities do pvs only
5080                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5081                                         ent->last_trace_visibility = realtime;
5082                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5083                                         r_refdef.viewcache.entityvisible[i] = 0;
5084                         }
5085                 }
5086         }
5087 }
5088
5089 /// only used if skyrendermasked, and normally returns false
5090 static int R_DrawBrushModelsSky (void)
5091 {
5092         int i, sky;
5093         entity_render_t *ent;
5094
5095         sky = false;
5096         for (i = 0;i < r_refdef.scene.numentities;i++)
5097         {
5098                 if (!r_refdef.viewcache.entityvisible[i])
5099                         continue;
5100                 ent = r_refdef.scene.entities[i];
5101                 if (!ent->model || !ent->model->DrawSky)
5102                         continue;
5103                 ent->model->DrawSky(ent);
5104                 sky = true;
5105         }
5106         return sky;
5107 }
5108
5109 static void R_DrawNoModel(entity_render_t *ent);
5110 static void R_DrawModels(void)
5111 {
5112         int i;
5113         entity_render_t *ent;
5114
5115         for (i = 0;i < r_refdef.scene.numentities;i++)
5116         {
5117                 if (!r_refdef.viewcache.entityvisible[i])
5118                         continue;
5119                 ent = r_refdef.scene.entities[i];
5120                 r_refdef.stats.entities++;
5121                 /*
5122                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5123                 {
5124                         vec3_t f, l, u, o;
5125                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5126                         Con_Printf("R_DrawModels\n");
5127                         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]);
5128                         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);
5129                         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);
5130                 }
5131                 */
5132                 if (ent->model && ent->model->Draw != NULL)
5133                         ent->model->Draw(ent);
5134                 else
5135                         R_DrawNoModel(ent);
5136         }
5137 }
5138
5139 static void R_DrawModelsDepth(void)
5140 {
5141         int i;
5142         entity_render_t *ent;
5143
5144         for (i = 0;i < r_refdef.scene.numentities;i++)
5145         {
5146                 if (!r_refdef.viewcache.entityvisible[i])
5147                         continue;
5148                 ent = r_refdef.scene.entities[i];
5149                 if (ent->model && ent->model->DrawDepth != NULL)
5150                         ent->model->DrawDepth(ent);
5151         }
5152 }
5153
5154 static void R_DrawModelsDebug(void)
5155 {
5156         int i;
5157         entity_render_t *ent;
5158
5159         for (i = 0;i < r_refdef.scene.numentities;i++)
5160         {
5161                 if (!r_refdef.viewcache.entityvisible[i])
5162                         continue;
5163                 ent = r_refdef.scene.entities[i];
5164                 if (ent->model && ent->model->DrawDebug != NULL)
5165                         ent->model->DrawDebug(ent);
5166         }
5167 }
5168
5169 static void R_DrawModelsAddWaterPlanes(void)
5170 {
5171         int i;
5172         entity_render_t *ent;
5173
5174         for (i = 0;i < r_refdef.scene.numentities;i++)
5175         {
5176                 if (!r_refdef.viewcache.entityvisible[i])
5177                         continue;
5178                 ent = r_refdef.scene.entities[i];
5179                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5180                         ent->model->DrawAddWaterPlanes(ent);
5181         }
5182 }
5183
5184 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}};
5185
5186 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5187 {
5188         if (r_hdr_irisadaptation.integer)
5189         {
5190                 vec3_t p;
5191                 vec3_t ambient;
5192                 vec3_t diffuse;
5193                 vec3_t diffusenormal;
5194                 vec3_t forward;
5195                 vec_t brightness = 0.0f;
5196                 vec_t goal;
5197                 vec_t current;
5198                 vec_t d;
5199                 int c;
5200                 VectorCopy(r_refdef.view.forward, forward);
5201                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5202                 {
5203                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5204                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5205                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5206                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5207                         d = DotProduct(forward, diffusenormal);
5208                         brightness += VectorLength(ambient);
5209                         if (d > 0)
5210                                 brightness += d * VectorLength(diffuse);
5211                 }
5212                 brightness *= 1.0f / c;
5213                 brightness += 0.00001f; // make sure it's never zero
5214                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5215                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5216                 current = r_hdr_irisadaptation_value.value;
5217                 if (current < goal)
5218                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5219                 else if (current > goal)
5220                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5221                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5222                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5223         }
5224         else if (r_hdr_irisadaptation_value.value != 1.0f)
5225                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5226 }
5227
5228 static void R_View_SetFrustum(const int *scissor)
5229 {
5230         int i;
5231         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5232         vec3_t forward, left, up, origin, v;
5233
5234         if(scissor)
5235         {
5236                 // flipped x coordinates (because x points left here)
5237                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5238                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5239
5240                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5241                 switch(vid.renderpath)
5242                 {
5243                         case RENDERPATH_D3D9:
5244                         case RENDERPATH_D3D10:
5245                         case RENDERPATH_D3D11:
5246                                 // non-flipped y coordinates
5247                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5248                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5249                                 break;
5250                         case RENDERPATH_SOFT:
5251                         case RENDERPATH_GL11:
5252                         case RENDERPATH_GL13:
5253                         case RENDERPATH_GL20:
5254                         case RENDERPATH_GLES1:
5255                         case RENDERPATH_GLES2:
5256                                 // non-flipped y coordinates
5257                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5258                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5259                                 break;
5260                 }
5261         }
5262
5263         // we can't trust r_refdef.view.forward and friends in reflected scenes
5264         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5265
5266 #if 0
5267         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5268         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5269         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5270         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5271         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5272         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5273         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5274         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5275         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5276         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5277         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5278         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5279 #endif
5280
5281 #if 0
5282         zNear = r_refdef.nearclip;
5283         nudge = 1.0 - 1.0 / (1<<23);
5284         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5285         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5286         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5287         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5288         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5289         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5290         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5291         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5292 #endif
5293
5294
5295
5296 #if 0
5297         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5298         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5299         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5300         r_refdef.view.frustum[0].dist = m[15] - m[12];
5301
5302         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5303         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5304         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5305         r_refdef.view.frustum[1].dist = m[15] + m[12];
5306
5307         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5308         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5309         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5310         r_refdef.view.frustum[2].dist = m[15] - m[13];
5311
5312         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5313         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5314         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5315         r_refdef.view.frustum[3].dist = m[15] + m[13];
5316
5317         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5318         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5319         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5320         r_refdef.view.frustum[4].dist = m[15] - m[14];
5321
5322         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5323         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5324         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5325         r_refdef.view.frustum[5].dist = m[15] + m[14];
5326 #endif
5327
5328         if (r_refdef.view.useperspective)
5329         {
5330                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5331                 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]);
5332                 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]);
5333                 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]);
5334                 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]);
5335
5336                 // then the normals from the corners relative to origin
5337                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5338                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5339                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5340                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5341
5342                 // in a NORMAL view, forward cross left == up
5343                 // in a REFLECTED view, forward cross left == down
5344                 // so our cross products above need to be adjusted for a left handed coordinate system
5345                 CrossProduct(forward, left, v);
5346                 if(DotProduct(v, up) < 0)
5347                 {
5348                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5349                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5350                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5351                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5352                 }
5353
5354                 // Leaving those out was a mistake, those were in the old code, and they
5355                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5356                 // I couldn't reproduce it after adding those normalizations. --blub
5357                 VectorNormalize(r_refdef.view.frustum[0].normal);
5358                 VectorNormalize(r_refdef.view.frustum[1].normal);
5359                 VectorNormalize(r_refdef.view.frustum[2].normal);
5360                 VectorNormalize(r_refdef.view.frustum[3].normal);
5361
5362                 // make the corners absolute
5363                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5364                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5365                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5366                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5367
5368                 // one more normal
5369                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5370
5371                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5372                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5373                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5374                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5375                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5376         }
5377         else
5378         {
5379                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5380                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5381                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5382                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5383                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5384                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5385                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5386                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5387                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5388                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5389         }
5390         r_refdef.view.numfrustumplanes = 5;
5391
5392         if (r_refdef.view.useclipplane)
5393         {
5394                 r_refdef.view.numfrustumplanes = 6;
5395                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5396         }
5397
5398         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5399                 PlaneClassify(r_refdef.view.frustum + i);
5400
5401         // LordHavoc: note to all quake engine coders, Quake had a special case
5402         // for 90 degrees which assumed a square view (wrong), so I removed it,
5403         // Quake2 has it disabled as well.
5404
5405         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5406         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5407         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5408         //PlaneClassify(&frustum[0]);
5409
5410         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5411         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5412         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5413         //PlaneClassify(&frustum[1]);
5414
5415         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5416         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5417         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5418         //PlaneClassify(&frustum[2]);
5419
5420         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5421         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5422         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5423         //PlaneClassify(&frustum[3]);
5424
5425         // nearclip plane
5426         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5427         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5428         //PlaneClassify(&frustum[4]);
5429 }
5430
5431 static void R_View_UpdateWithScissor(const int *myscissor)
5432 {
5433         R_Main_ResizeViewCache();
5434         R_View_SetFrustum(myscissor);
5435         R_View_WorldVisibility(r_refdef.view.useclipplane);
5436         R_View_UpdateEntityVisible();
5437         R_View_UpdateEntityLighting();
5438 }
5439
5440 static void R_View_Update(void)
5441 {
5442         R_Main_ResizeViewCache();
5443         R_View_SetFrustum(NULL);
5444         R_View_WorldVisibility(r_refdef.view.useclipplane);
5445         R_View_UpdateEntityVisible();
5446         R_View_UpdateEntityLighting();
5447 }
5448
5449 float viewscalefpsadjusted = 1.0f;
5450
5451 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5452 {
5453         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5454         scale = bound(0.03125f, scale, 1.0f);
5455         *outwidth = (int)ceil(width * scale);
5456         *outheight = (int)ceil(height * scale);
5457 }
5458
5459 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5460 {
5461         const float *customclipplane = NULL;
5462         float plane[4];
5463         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5464         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5465         {
5466                 // LordHavoc: couldn't figure out how to make this approach the
5467                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5468                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5469                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5470                         dist = r_refdef.view.clipplane.dist;
5471                 plane[0] = r_refdef.view.clipplane.normal[0];
5472                 plane[1] = r_refdef.view.clipplane.normal[1];
5473                 plane[2] = r_refdef.view.clipplane.normal[2];
5474                 plane[3] = -dist;
5475                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5476         }
5477
5478         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5479         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5480
5481         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5482         if (!r_refdef.view.useperspective)
5483                 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);
5484         else if (vid.stencil && r_useinfinitefarclip.integer)
5485                 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);
5486         else
5487                 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);
5488         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5489         R_SetViewport(&r_refdef.view.viewport);
5490         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5491         {
5492                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5493                 float screenplane[4];
5494                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5495                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5496                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5497                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5498                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5499         }
5500 }
5501
5502 void R_EntityMatrix(const matrix4x4_t *matrix)
5503 {
5504         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5505         {
5506                 gl_modelmatrixchanged = false;
5507                 gl_modelmatrix = *matrix;
5508                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5509                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5510                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5511                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5512                 CHECKGLERROR
5513                 switch(vid.renderpath)
5514                 {
5515                 case RENDERPATH_D3D9:
5516 #ifdef SUPPORTD3D
5517                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5518                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5519 #endif
5520                         break;
5521                 case RENDERPATH_D3D10:
5522                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5523                         break;
5524                 case RENDERPATH_D3D11:
5525                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5526                         break;
5527                 case RENDERPATH_GL11:
5528                 case RENDERPATH_GL13:
5529                 case RENDERPATH_GLES1:
5530                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5531                         break;
5532                 case RENDERPATH_SOFT:
5533                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5534                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5535                         break;
5536                 case RENDERPATH_GL20:
5537                 case RENDERPATH_GLES2:
5538                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5539                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5540                         break;
5541                 }
5542         }
5543 }
5544
5545 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5546 {
5547         r_viewport_t viewport;
5548
5549         CHECKGLERROR
5550
5551         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5552         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);
5553         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5554         R_SetViewport(&viewport);
5555         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5556         GL_Color(1, 1, 1, 1);
5557         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5558         GL_BlendFunc(GL_ONE, GL_ZERO);
5559         GL_ScissorTest(false);
5560         GL_DepthMask(false);
5561         GL_DepthRange(0, 1);
5562         GL_DepthTest(false);
5563         GL_DepthFunc(GL_LEQUAL);
5564         R_EntityMatrix(&identitymatrix);
5565         R_Mesh_ResetTextureState();
5566         GL_PolygonOffset(0, 0);
5567         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5568         switch(vid.renderpath)
5569         {
5570         case RENDERPATH_GL11:
5571         case RENDERPATH_GL13:
5572         case RENDERPATH_GL20:
5573         case RENDERPATH_GLES1:
5574         case RENDERPATH_GLES2:
5575                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5576                 break;
5577         case RENDERPATH_D3D9:
5578         case RENDERPATH_D3D10:
5579         case RENDERPATH_D3D11:
5580         case RENDERPATH_SOFT:
5581                 break;
5582         }
5583         GL_CullFace(GL_NONE);
5584
5585         CHECKGLERROR
5586 }
5587
5588 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5589 {
5590         DrawQ_Finish();
5591
5592         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5593 }
5594
5595 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5596 {
5597         DrawQ_Finish();
5598
5599         R_SetupView(true, fbo, depthtexture, colortexture);
5600         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5601         GL_Color(1, 1, 1, 1);
5602         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5603         GL_BlendFunc(GL_ONE, GL_ZERO);
5604         GL_ScissorTest(true);
5605         GL_DepthMask(true);
5606         GL_DepthRange(0, 1);
5607         GL_DepthTest(true);
5608         GL_DepthFunc(GL_LEQUAL);
5609         R_EntityMatrix(&identitymatrix);
5610         R_Mesh_ResetTextureState();
5611         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5612         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5613         switch(vid.renderpath)
5614         {
5615         case RENDERPATH_GL11:
5616         case RENDERPATH_GL13:
5617         case RENDERPATH_GL20:
5618         case RENDERPATH_GLES1:
5619         case RENDERPATH_GLES2:
5620                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5621                 break;
5622         case RENDERPATH_D3D9:
5623         case RENDERPATH_D3D10:
5624         case RENDERPATH_D3D11:
5625         case RENDERPATH_SOFT:
5626                 break;
5627         }
5628         GL_CullFace(r_refdef.view.cullface_back);
5629 }
5630
5631 /*
5632 ================
5633 R_RenderView_UpdateViewVectors
5634 ================
5635 */
5636 void R_RenderView_UpdateViewVectors(void)
5637 {
5638         // break apart the view matrix into vectors for various purposes
5639         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5640         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5641         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5642         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5643         // make an inverted copy of the view matrix for tracking sprites
5644         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5645 }
5646
5647 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5648 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5649
5650 static void R_Water_StartFrame(void)
5651 {
5652         int i;
5653         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5654         r_waterstate_waterplane_t *p;
5655         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;
5656
5657         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5658                 return;
5659
5660         switch(vid.renderpath)
5661         {
5662         case RENDERPATH_GL20:
5663         case RENDERPATH_D3D9:
5664         case RENDERPATH_D3D10:
5665         case RENDERPATH_D3D11:
5666         case RENDERPATH_SOFT:
5667         case RENDERPATH_GLES2:
5668                 break;
5669         case RENDERPATH_GL11:
5670         case RENDERPATH_GL13:
5671         case RENDERPATH_GLES1:
5672                 return;
5673         }
5674
5675         // set waterwidth and waterheight to the water resolution that will be
5676         // used (often less than the screen resolution for faster rendering)
5677         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5678
5679         // calculate desired texture sizes
5680         // can't use water if the card does not support the texture size
5681         if (!r_water.integer || r_showsurfaces.integer)
5682                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5683         else if (vid.support.arb_texture_non_power_of_two)
5684         {
5685                 texturewidth = waterwidth;
5686                 textureheight = waterheight;
5687                 camerawidth = waterwidth;
5688                 cameraheight = waterheight;
5689         }
5690         else
5691         {
5692                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5693                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5694                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5695                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5696         }
5697
5698         // allocate textures as needed
5699         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))
5700         {
5701                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5702                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5703                 {
5704                         if (p->texture_refraction)
5705                                 R_FreeTexture(p->texture_refraction);
5706                         p->texture_refraction = NULL;
5707                         if (p->fbo_refraction)
5708                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5709                         p->fbo_refraction = 0;
5710                         if (p->texture_reflection)
5711                                 R_FreeTexture(p->texture_reflection);
5712                         p->texture_reflection = NULL;
5713                         if (p->fbo_reflection)
5714                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5715                         p->fbo_reflection = 0;
5716                         if (p->texture_camera)
5717                                 R_FreeTexture(p->texture_camera);
5718                         p->texture_camera = NULL;
5719                         if (p->fbo_camera)
5720                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5721                         p->fbo_camera = 0;
5722                 }
5723                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5724                 r_fb.water.texturewidth = texturewidth;
5725                 r_fb.water.textureheight = textureheight;
5726                 r_fb.water.camerawidth = camerawidth;
5727                 r_fb.water.cameraheight = cameraheight;
5728         }
5729
5730         if (r_fb.water.texturewidth)
5731         {
5732                 int scaledwidth, scaledheight;
5733
5734                 r_fb.water.enabled = true;
5735
5736                 // water resolution is usually reduced
5737                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5738                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5739                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5740
5741                 // set up variables that will be used in shader setup
5742                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5743                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5744                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5745                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5746         }
5747
5748         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5749         r_fb.water.numwaterplanes = 0;
5750 }
5751
5752 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5753 {
5754         int planeindex, bestplaneindex, vertexindex;
5755         vec3_t mins, maxs, normal, center, v, n;
5756         vec_t planescore, bestplanescore;
5757         mplane_t plane;
5758         r_waterstate_waterplane_t *p;
5759         texture_t *t = R_GetCurrentTexture(surface->texture);
5760
5761         rsurface.texture = t;
5762         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5763         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5764         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5765                 return;
5766         // average the vertex normals, find the surface bounds (after deformvertexes)
5767         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5768         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5769         VectorCopy(n, normal);
5770         VectorCopy(v, mins);
5771         VectorCopy(v, maxs);
5772         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5773         {
5774                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5775                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5776                 VectorAdd(normal, n, normal);
5777                 mins[0] = min(mins[0], v[0]);
5778                 mins[1] = min(mins[1], v[1]);
5779                 mins[2] = min(mins[2], v[2]);
5780                 maxs[0] = max(maxs[0], v[0]);
5781                 maxs[1] = max(maxs[1], v[1]);
5782                 maxs[2] = max(maxs[2], v[2]);
5783         }
5784         VectorNormalize(normal);
5785         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5786
5787         VectorCopy(normal, plane.normal);
5788         VectorNormalize(plane.normal);
5789         plane.dist = DotProduct(center, plane.normal);
5790         PlaneClassify(&plane);
5791         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5792         {
5793                 // skip backfaces (except if nocullface is set)
5794 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5795 //                      return;
5796                 VectorNegate(plane.normal, plane.normal);
5797                 plane.dist *= -1;
5798                 PlaneClassify(&plane);
5799         }
5800
5801
5802         // find a matching plane if there is one
5803         bestplaneindex = -1;
5804         bestplanescore = 1048576.0f;
5805         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5806         {
5807                 if(p->camera_entity == t->camera_entity)
5808                 {
5809                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5810                         if (bestplaneindex < 0 || bestplanescore > planescore)
5811                         {
5812                                 bestplaneindex = planeindex;
5813                                 bestplanescore = planescore;
5814                         }
5815                 }
5816         }
5817         planeindex = bestplaneindex;
5818         p = r_fb.water.waterplanes + planeindex;
5819
5820         // if this surface does not fit any known plane rendered this frame, add one
5821         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5822         {
5823                 // store the new plane
5824                 planeindex = r_fb.water.numwaterplanes++;
5825                 p = r_fb.water.waterplanes + planeindex;
5826                 p->plane = plane;
5827                 // clear materialflags and pvs
5828                 p->materialflags = 0;
5829                 p->pvsvalid = false;
5830                 p->camera_entity = t->camera_entity;
5831                 VectorCopy(mins, p->mins);
5832                 VectorCopy(maxs, p->maxs);
5833         }
5834         else
5835         {
5836                 // merge mins/maxs when we're adding this surface to the plane
5837                 p->mins[0] = min(p->mins[0], mins[0]);
5838                 p->mins[1] = min(p->mins[1], mins[1]);
5839                 p->mins[2] = min(p->mins[2], mins[2]);
5840                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5841                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5842                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5843         }
5844         // merge this surface's materialflags into the waterplane
5845         p->materialflags |= t->currentmaterialflags;
5846         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5847         {
5848                 // merge this surface's PVS into the waterplane
5849                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5850                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5851                 {
5852                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5853                         p->pvsvalid = true;
5854                 }
5855         }
5856 }
5857
5858 extern cvar_t r_drawparticles;
5859 extern cvar_t r_drawdecals;
5860
5861 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5862 {
5863         int myscissor[4];
5864         r_refdef_view_t originalview;
5865         r_refdef_view_t myview;
5866         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;
5867         r_waterstate_waterplane_t *p;
5868         vec3_t visorigin;
5869         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;
5870         char vabuf[1024];
5871
5872         originalview = r_refdef.view;
5873
5874         // lowquality hack, temporarily shut down some cvars and restore afterwards
5875         qualityreduction = r_water_lowquality.integer;
5876         if (qualityreduction > 0)
5877         {
5878                 if (qualityreduction >= 1)
5879                 {
5880                         old_r_shadows = r_shadows.integer;
5881                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5882                         old_r_dlight = r_shadow_realtime_dlight.integer;
5883                         Cvar_SetValueQuick(&r_shadows, 0);
5884                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5885                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5886                 }
5887                 if (qualityreduction >= 2)
5888                 {
5889                         old_r_dynamic = r_dynamic.integer;
5890                         old_r_particles = r_drawparticles.integer;
5891                         old_r_decals = r_drawdecals.integer;
5892                         Cvar_SetValueQuick(&r_dynamic, 0);
5893                         Cvar_SetValueQuick(&r_drawparticles, 0);
5894                         Cvar_SetValueQuick(&r_drawdecals, 0);
5895                 }
5896         }
5897
5898         // make sure enough textures are allocated
5899         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5900         {
5901                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5902                 {
5903                         if (!p->texture_refraction)
5904                                 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);
5905                         if (!p->texture_refraction)
5906                                 goto error;
5907                         if (usewaterfbo)
5908                         {
5909                                 if (r_fb.water.depthtexture == NULL)
5910                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5911                                 if (p->fbo_refraction == 0)
5912                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5913                         }
5914                 }
5915                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5916                 {
5917                         if (!p->texture_camera)
5918                                 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);
5919                         if (!p->texture_camera)
5920                                 goto error;
5921                         if (usewaterfbo)
5922                         {
5923                                 if (r_fb.water.depthtexture == NULL)
5924                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5925                                 if (p->fbo_camera == 0)
5926                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5927                         }
5928                 }
5929
5930                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5931                 {
5932                         if (!p->texture_reflection)
5933                                 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);
5934                         if (!p->texture_reflection)
5935                                 goto error;
5936                         if (usewaterfbo)
5937                         {
5938                                 if (r_fb.water.depthtexture == NULL)
5939                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5940                                 if (p->fbo_reflection == 0)
5941                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5942                         }
5943                 }
5944         }
5945
5946         // render views
5947         r_refdef.view = originalview;
5948         r_refdef.view.showdebug = false;
5949         r_refdef.view.width = r_fb.water.waterwidth;
5950         r_refdef.view.height = r_fb.water.waterheight;
5951         r_refdef.view.useclipplane = true;
5952         myview = r_refdef.view;
5953         r_fb.water.renderingscene = true;
5954         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5955         {
5956                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5957                 {
5958                         r_refdef.view = myview;
5959                         if(r_water_scissormode.integer)
5960                         {
5961                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5962                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5963                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5964                         }
5965
5966                         // render reflected scene and copy into texture
5967                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5968                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5969                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5970                         r_refdef.view.clipplane = p->plane;
5971                         // reverse the cullface settings for this render
5972                         r_refdef.view.cullface_front = GL_FRONT;
5973                         r_refdef.view.cullface_back = GL_BACK;
5974                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5975                         {
5976                                 r_refdef.view.usecustompvs = true;
5977                                 if (p->pvsvalid)
5978                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5979                                 else
5980                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5981                         }
5982
5983                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5984                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5985                         R_ClearScreen(r_refdef.fogenabled);
5986                         if(r_water_scissormode.integer & 2)
5987                                 R_View_UpdateWithScissor(myscissor);
5988                         else
5989                                 R_View_Update();
5990                         R_AnimCache_CacheVisibleEntities();
5991                         if(r_water_scissormode.integer & 1)
5992                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5993                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5994
5995                         if (!p->fbo_reflection)
5996                                 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);
5997                         r_fb.water.hideplayer = false;
5998                 }
5999
6000                 // render the normal view scene and copy into texture
6001                 // (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)
6002                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6003                 {
6004                         r_refdef.view = myview;
6005                         if(r_water_scissormode.integer)
6006                         {
6007                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6008                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6009                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6010                         }
6011
6012                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6013
6014                         r_refdef.view.clipplane = p->plane;
6015                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6016                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6017
6018                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6019                         {
6020                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6021                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6022                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6023                                 R_RenderView_UpdateViewVectors();
6024                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6025                                 {
6026                                         r_refdef.view.usecustompvs = true;
6027                                         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);
6028                                 }
6029                         }
6030
6031                         PlaneClassify(&r_refdef.view.clipplane);
6032
6033                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6034                         R_ClearScreen(r_refdef.fogenabled);
6035                         if(r_water_scissormode.integer & 2)
6036                                 R_View_UpdateWithScissor(myscissor);
6037                         else
6038                                 R_View_Update();
6039                         R_AnimCache_CacheVisibleEntities();
6040                         if(r_water_scissormode.integer & 1)
6041                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6042                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6043
6044                         if (!p->fbo_refraction)
6045                                 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);
6046                         r_fb.water.hideplayer = false;
6047                 }
6048                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6049                 {
6050                         r_refdef.view = myview;
6051
6052                         r_refdef.view.clipplane = p->plane;
6053                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6054                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6055
6056                         r_refdef.view.width = r_fb.water.camerawidth;
6057                         r_refdef.view.height = r_fb.water.cameraheight;
6058                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6059                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6060                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6061                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6062
6063                         if(p->camera_entity)
6064                         {
6065                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6066                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6067                         }
6068
6069                         // note: all of the view is used for displaying... so
6070                         // there is no use in scissoring
6071
6072                         // reverse the cullface settings for this render
6073                         r_refdef.view.cullface_front = GL_FRONT;
6074                         r_refdef.view.cullface_back = GL_BACK;
6075                         // also reverse the view matrix
6076                         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
6077                         R_RenderView_UpdateViewVectors();
6078                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6079                         {
6080                                 r_refdef.view.usecustompvs = true;
6081                                 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);
6082                         }
6083                         
6084                         // camera needs no clipplane
6085                         r_refdef.view.useclipplane = false;
6086
6087                         PlaneClassify(&r_refdef.view.clipplane);
6088
6089                         r_fb.water.hideplayer = false;
6090
6091                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6092                         R_ClearScreen(r_refdef.fogenabled);
6093                         R_View_Update();
6094                         R_AnimCache_CacheVisibleEntities();
6095                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6096
6097                         if (!p->fbo_camera)
6098                                 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);
6099                         r_fb.water.hideplayer = false;
6100                 }
6101
6102         }
6103         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6104         r_fb.water.renderingscene = false;
6105         r_refdef.view = originalview;
6106         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6107         if (!r_fb.water.depthtexture)
6108                 R_ClearScreen(r_refdef.fogenabled);
6109         R_View_Update();
6110         R_AnimCache_CacheVisibleEntities();
6111         goto finish;
6112 error:
6113         r_refdef.view = originalview;
6114         r_fb.water.renderingscene = false;
6115         Cvar_SetValueQuick(&r_water, 0);
6116         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6117 finish:
6118         // lowquality hack, restore cvars
6119         if (qualityreduction > 0)
6120         {
6121                 if (qualityreduction >= 1)
6122                 {
6123                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6124                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6125                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6126                 }
6127                 if (qualityreduction >= 2)
6128                 {
6129                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6130                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6131                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6132                 }
6133         }
6134 }
6135
6136 static void R_Bloom_StartFrame(void)
6137 {
6138         int i;
6139         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6140         int viewwidth, viewheight;
6141         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6142         textype_t textype = TEXTYPE_COLORBUFFER;
6143
6144         switch (vid.renderpath)
6145         {
6146         case RENDERPATH_GL20:
6147                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6148                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6149                 {
6150                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6151                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6152                 }
6153                 break;
6154         case RENDERPATH_GL11:
6155         case RENDERPATH_GL13:
6156         case RENDERPATH_GLES1:
6157         case RENDERPATH_GLES2:
6158         case RENDERPATH_D3D9:
6159         case RENDERPATH_D3D10:
6160         case RENDERPATH_D3D11:
6161                 r_fb.usedepthtextures = false;
6162                 break;
6163         case RENDERPATH_SOFT:
6164                 r_fb.usedepthtextures = true;
6165                 break;
6166         }
6167
6168         if (r_viewscale_fpsscaling.integer)
6169         {
6170                 double actualframetime;
6171                 double targetframetime;
6172                 double adjust;
6173                 actualframetime = r_refdef.lastdrawscreentime;
6174                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6175                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6176                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6177                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6178                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6179                 viewscalefpsadjusted += adjust;
6180                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6181         }
6182         else
6183                 viewscalefpsadjusted = 1.0f;
6184
6185         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6186
6187         switch(vid.renderpath)
6188         {
6189         case RENDERPATH_GL20:
6190         case RENDERPATH_D3D9:
6191         case RENDERPATH_D3D10:
6192         case RENDERPATH_D3D11:
6193         case RENDERPATH_SOFT:
6194         case RENDERPATH_GLES2:
6195                 break;
6196         case RENDERPATH_GL11:
6197         case RENDERPATH_GL13:
6198         case RENDERPATH_GLES1:
6199                 return;
6200         }
6201
6202         // set bloomwidth and bloomheight to the bloom resolution that will be
6203         // used (often less than the screen resolution for faster rendering)
6204         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6205         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6206         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6207         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6208         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6209
6210         // calculate desired texture sizes
6211         if (vid.support.arb_texture_non_power_of_two)
6212         {
6213                 screentexturewidth = vid.width;
6214                 screentextureheight = vid.height;
6215                 bloomtexturewidth = r_fb.bloomwidth;
6216                 bloomtextureheight = r_fb.bloomheight;
6217         }
6218         else
6219         {
6220                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6221                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6222                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6223                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6224         }
6225
6226         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))
6227         {
6228                 Cvar_SetValueQuick(&r_bloom, 0);
6229                 Cvar_SetValueQuick(&r_motionblur, 0);
6230                 Cvar_SetValueQuick(&r_damageblur, 0);
6231         }
6232
6233         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6234          && !r_bloom.integer
6235          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6236          && !useviewfbo
6237          && r_viewscale.value == 1.0f
6238          && !r_viewscale_fpsscaling.integer)
6239                 screentexturewidth = screentextureheight = 0;
6240         if (!r_bloom.integer)
6241                 bloomtexturewidth = bloomtextureheight = 0;
6242
6243         // allocate textures as needed
6244         if (r_fb.screentexturewidth != screentexturewidth
6245          || r_fb.screentextureheight != screentextureheight
6246          || r_fb.bloomtexturewidth != bloomtexturewidth
6247          || r_fb.bloomtextureheight != bloomtextureheight
6248          || r_fb.textype != textype
6249          || useviewfbo != (r_fb.fbo != 0))
6250         {
6251                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6252                 {
6253                         if (r_fb.bloomtexture[i])
6254                                 R_FreeTexture(r_fb.bloomtexture[i]);
6255                         r_fb.bloomtexture[i] = NULL;
6256
6257                         if (r_fb.bloomfbo[i])
6258                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6259                         r_fb.bloomfbo[i] = 0;
6260                 }
6261
6262                 if (r_fb.fbo)
6263                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6264                 r_fb.fbo = 0;
6265
6266                 if (r_fb.colortexture)
6267                         R_FreeTexture(r_fb.colortexture);
6268                 r_fb.colortexture = NULL;
6269
6270                 if (r_fb.depthtexture)
6271                         R_FreeTexture(r_fb.depthtexture);
6272                 r_fb.depthtexture = NULL;
6273
6274                 if (r_fb.ghosttexture)
6275                         R_FreeTexture(r_fb.ghosttexture);
6276                 r_fb.ghosttexture = NULL;
6277
6278                 r_fb.screentexturewidth = screentexturewidth;
6279                 r_fb.screentextureheight = screentextureheight;
6280                 r_fb.bloomtexturewidth = bloomtexturewidth;
6281                 r_fb.bloomtextureheight = bloomtextureheight;
6282                 r_fb.textype = textype;
6283
6284                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6285                 {
6286                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6287                                 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);
6288                         r_fb.ghosttexture_valid = false;
6289                         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);
6290                         if (useviewfbo)
6291                         {
6292                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6293                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6294                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6295                         }
6296                 }
6297
6298                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6299                 {
6300                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6301                         {
6302                                 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);
6303                                 if (useviewfbo)
6304                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6305                         }
6306                 }
6307         }
6308
6309         // bloom texture is a different resolution
6310         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6311         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6312         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6313         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6314         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6315
6316         // set up a texcoord array for the full resolution screen image
6317         // (we have to keep this around to copy back during final render)
6318         r_fb.screentexcoord2f[0] = 0;
6319         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6320         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6321         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6322         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6323         r_fb.screentexcoord2f[5] = 0;
6324         r_fb.screentexcoord2f[6] = 0;
6325         r_fb.screentexcoord2f[7] = 0;
6326
6327         if(r_fb.fbo) 
6328         {
6329                 for (i = 1;i < 8;i += 2)
6330                 {
6331                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6332                 }
6333         }
6334
6335         // set up a texcoord array for the reduced resolution bloom image
6336         // (which will be additive blended over the screen image)
6337         r_fb.bloomtexcoord2f[0] = 0;
6338         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6339         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6340         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6341         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6342         r_fb.bloomtexcoord2f[5] = 0;
6343         r_fb.bloomtexcoord2f[6] = 0;
6344         r_fb.bloomtexcoord2f[7] = 0;
6345
6346         switch(vid.renderpath)
6347         {
6348         case RENDERPATH_GL11:
6349         case RENDERPATH_GL13:
6350         case RENDERPATH_GL20:
6351         case RENDERPATH_SOFT:
6352         case RENDERPATH_GLES1:
6353         case RENDERPATH_GLES2:
6354                 break;
6355         case RENDERPATH_D3D9:
6356         case RENDERPATH_D3D10:
6357         case RENDERPATH_D3D11:
6358                 for (i = 0;i < 4;i++)
6359                 {
6360                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6361                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6362                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6363                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6364                 }
6365                 break;
6366         }
6367
6368         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6369
6370         if (r_fb.fbo)
6371                 r_refdef.view.clear = true;
6372 }
6373
6374 static void R_Bloom_MakeTexture(void)
6375 {
6376         int x, range, dir;
6377         float xoffset, yoffset, r, brighten;
6378         rtexture_t *intex;
6379         float colorscale = r_bloom_colorscale.value;
6380
6381         r_refdef.stats.bloom++;
6382     
6383 #if 0
6384     // this copy is unnecessary since it happens in R_BlendView already
6385         if (!r_fb.fbo)
6386         {
6387                 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);
6388                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6389         }
6390 #endif
6391
6392         // scale down screen texture to the bloom texture size
6393         CHECKGLERROR
6394         r_fb.bloomindex = 0;
6395         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6396         R_SetViewport(&r_fb.bloomviewport);
6397         GL_DepthTest(false);
6398         GL_BlendFunc(GL_ONE, GL_ZERO);
6399         GL_Color(colorscale, colorscale, colorscale, 1);
6400         // 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...
6401         switch(vid.renderpath)
6402         {
6403         case RENDERPATH_GL11:
6404         case RENDERPATH_GL13:
6405         case RENDERPATH_GL20:
6406         case RENDERPATH_GLES1:
6407         case RENDERPATH_GLES2:
6408         case RENDERPATH_SOFT:
6409                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6410                 break;
6411         case RENDERPATH_D3D9:
6412         case RENDERPATH_D3D10:
6413         case RENDERPATH_D3D11:
6414                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6415                 break;
6416         }
6417         // TODO: do boxfilter scale-down in shader?
6418         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6419         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6420         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6421
6422         // we now have a properly scaled bloom image
6423         if (!r_fb.bloomfbo[r_fb.bloomindex])
6424         {
6425                 // copy it into the bloom texture
6426                 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);
6427                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6428         }
6429
6430         // multiply bloom image by itself as many times as desired
6431         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6432         {
6433                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6434                 r_fb.bloomindex ^= 1;
6435                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6436                 x *= 2;
6437                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6438                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6439                 {
6440                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6441                         GL_Color(r,r,r,1); // apply fix factor
6442                 }
6443                 else
6444                 {
6445                         if(x <= 2)
6446                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6447                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6448                         GL_Color(1,1,1,1); // no fix factor supported here
6449                 }
6450                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6451                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6452                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6453                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6454
6455                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6456                 {
6457                         // copy the darkened image to a texture
6458                         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);
6459                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6460                 }
6461         }
6462
6463         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6464         brighten = r_bloom_brighten.value;
6465         brighten = sqrt(brighten);
6466         if(range >= 1)
6467                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6468
6469         for (dir = 0;dir < 2;dir++)
6470         {
6471                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6472                 r_fb.bloomindex ^= 1;
6473                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6474                 // blend on at multiple vertical offsets to achieve a vertical blur
6475                 // TODO: do offset blends using GLSL
6476                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6477                 GL_BlendFunc(GL_ONE, GL_ZERO);
6478                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6479                 for (x = -range;x <= range;x++)
6480                 {
6481                         if (!dir){xoffset = 0;yoffset = x;}
6482                         else {xoffset = x;yoffset = 0;}
6483                         xoffset /= (float)r_fb.bloomtexturewidth;
6484                         yoffset /= (float)r_fb.bloomtextureheight;
6485                         // compute a texcoord array with the specified x and y offset
6486                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6487                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6488                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6489                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6490                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6491                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6492                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6493                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6494                         // this r value looks like a 'dot' particle, fading sharply to
6495                         // black at the edges
6496                         // (probably not realistic but looks good enough)
6497                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6498                         //r = brighten/(range*2+1);
6499                         r = brighten / (range * 2 + 1);
6500                         if(range >= 1)
6501                                 r *= (1 - x*x/(float)(range*range));
6502                         GL_Color(r, r, r, 1);
6503                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6504                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6505                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6506                         GL_BlendFunc(GL_ONE, GL_ONE);
6507                 }
6508
6509                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6510                 {
6511                         // copy the vertically or horizontally blurred bloom view to a texture
6512                         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);
6513                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6514                 }
6515         }
6516 }
6517
6518 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6519 {
6520         unsigned int permutation;
6521         float uservecs[4][4];
6522
6523         R_EntityMatrix(&identitymatrix);
6524
6525         switch (vid.renderpath)
6526         {
6527         case RENDERPATH_GL20:
6528         case RENDERPATH_D3D9:
6529         case RENDERPATH_D3D10:
6530         case RENDERPATH_D3D11:
6531         case RENDERPATH_SOFT:
6532         case RENDERPATH_GLES2:
6533                 permutation =
6534                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6535                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6536                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6537                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6538                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6539
6540                 if (r_fb.colortexture)
6541                 {
6542                         if (!r_fb.fbo)
6543                         {
6544                                 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);
6545                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6546                         }
6547
6548                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6549                         {
6550                                 // declare variables
6551                                 float blur_factor, blur_mouseaccel, blur_velocity;
6552                                 static float blur_average; 
6553                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6554
6555                                 // set a goal for the factoring
6556                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6557                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6558                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6559                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6560                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6561                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6562
6563                                 // from the goal, pick an averaged value between goal and last value
6564                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6565                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6566
6567                                 // enforce minimum amount of blur 
6568                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6569
6570                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6571
6572                                 // calculate values into a standard alpha
6573                                 cl.motionbluralpha = 1 - exp(-
6574                                                 (
6575                                                  (r_motionblur.value * blur_factor / 80)
6576                                                  +
6577                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6578                                                 )
6579                                                 /
6580                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6581                                           );
6582
6583                                 // randomization for the blur value to combat persistent ghosting
6584                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6585                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6586
6587                                 // apply the blur
6588                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6589                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6590                                 {
6591                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6592                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6593                                         switch(vid.renderpath)
6594                                         {
6595                                         case RENDERPATH_GL11:
6596                                         case RENDERPATH_GL13:
6597                                         case RENDERPATH_GL20:
6598                                         case RENDERPATH_GLES1:
6599                                         case RENDERPATH_GLES2:
6600                                         case RENDERPATH_SOFT:
6601                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6602                                                 break;
6603                                         case RENDERPATH_D3D9:
6604                                         case RENDERPATH_D3D10:
6605                                         case RENDERPATH_D3D11:
6606                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6607                                                 break;
6608                                         }
6609                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6610                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6611                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6612                                 }
6613
6614                                 // updates old view angles for next pass
6615                                 VectorCopy(cl.viewangles, blur_oldangles);
6616
6617                                 // copy view into the ghost texture
6618                                 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);
6619                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6620                                 r_fb.ghosttexture_valid = true;
6621                         }
6622                 }
6623                 else
6624                 {
6625                         // no r_fb.colortexture means we're rendering to the real fb
6626                         // we may still have to do view tint...
6627                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6628                         {
6629                                 // apply a color tint to the whole view
6630                                 R_ResetViewRendering2D(0, NULL, NULL);
6631                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6632                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6633                                 R_SetupShader_Generic_NoTexture(false, true);
6634                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6635                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6636                         }
6637                         break; // no screen processing, no bloom, skip it
6638                 }
6639
6640                 if (r_fb.bloomtexture[0])
6641                 {
6642                         // make the bloom texture
6643                         R_Bloom_MakeTexture();
6644                 }
6645
6646 #if _MSC_VER >= 1400
6647 #define sscanf sscanf_s
6648 #endif
6649                 memset(uservecs, 0, sizeof(uservecs));
6650                 if (r_glsl_postprocess_uservec1_enable.integer)
6651                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6652                 if (r_glsl_postprocess_uservec2_enable.integer)
6653                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6654                 if (r_glsl_postprocess_uservec3_enable.integer)
6655                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6656                 if (r_glsl_postprocess_uservec4_enable.integer)
6657                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6658
6659                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6660                 GL_Color(1, 1, 1, 1);
6661                 GL_BlendFunc(GL_ONE, GL_ZERO);
6662
6663                 switch(vid.renderpath)
6664                 {
6665                 case RENDERPATH_GL20:
6666                 case RENDERPATH_GLES2:
6667                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6668                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6669                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6670                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6671                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6672                         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]);
6673                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6674                         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]);
6675                         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]);
6676                         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]);
6677                         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]);
6678                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6679                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6680                         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);
6681                         break;
6682                 case RENDERPATH_D3D9:
6683 #ifdef SUPPORTD3D
6684                         // 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...
6685                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6686                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6687                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6688                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6689                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6690                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6691                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6692                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6693                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6694                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6695                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6696                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6697                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6698                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6699 #endif
6700                         break;
6701                 case RENDERPATH_D3D10:
6702                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6703                         break;
6704                 case RENDERPATH_D3D11:
6705                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6706                         break;
6707                 case RENDERPATH_SOFT:
6708                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6709                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6710                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6711                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6712                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6713                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6714                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6715                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6716                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6717                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6718                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6719                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6720                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6721                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6722                         break;
6723                 default:
6724                         break;
6725                 }
6726                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6727                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6728                 break;
6729         case RENDERPATH_GL11:
6730         case RENDERPATH_GL13:
6731         case RENDERPATH_GLES1:
6732                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6733                 {
6734                         // apply a color tint to the whole view
6735                         R_ResetViewRendering2D(0, NULL, NULL);
6736                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6737                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6738                         R_SetupShader_Generic_NoTexture(false, true);
6739                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6740                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6741                 }
6742                 break;
6743         }
6744 }
6745
6746 matrix4x4_t r_waterscrollmatrix;
6747
6748 void R_UpdateFog(void)
6749 {
6750         // Nehahra fog
6751         if (gamemode == GAME_NEHAHRA)
6752         {
6753                 if (gl_fogenable.integer)
6754                 {
6755                         r_refdef.oldgl_fogenable = true;
6756                         r_refdef.fog_density = gl_fogdensity.value;
6757                         r_refdef.fog_red = gl_fogred.value;
6758                         r_refdef.fog_green = gl_foggreen.value;
6759                         r_refdef.fog_blue = gl_fogblue.value;
6760                         r_refdef.fog_alpha = 1;
6761                         r_refdef.fog_start = 0;
6762                         r_refdef.fog_end = gl_skyclip.value;
6763                         r_refdef.fog_height = 1<<30;
6764                         r_refdef.fog_fadedepth = 128;
6765                 }
6766                 else if (r_refdef.oldgl_fogenable)
6767                 {
6768                         r_refdef.oldgl_fogenable = false;
6769                         r_refdef.fog_density = 0;
6770                         r_refdef.fog_red = 0;
6771                         r_refdef.fog_green = 0;
6772                         r_refdef.fog_blue = 0;
6773                         r_refdef.fog_alpha = 0;
6774                         r_refdef.fog_start = 0;
6775                         r_refdef.fog_end = 0;
6776                         r_refdef.fog_height = 1<<30;
6777                         r_refdef.fog_fadedepth = 128;
6778                 }
6779         }
6780
6781         // fog parms
6782         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6783         r_refdef.fog_start = max(0, r_refdef.fog_start);
6784         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6785
6786         if (r_refdef.fog_density && r_drawfog.integer)
6787         {
6788                 r_refdef.fogenabled = true;
6789                 // this is the point where the fog reaches 0.9986 alpha, which we
6790                 // consider a good enough cutoff point for the texture
6791                 // (0.9986 * 256 == 255.6)
6792                 if (r_fog_exp2.integer)
6793                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6794                 else
6795                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6796                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6797                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6798                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6799                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6800                         R_BuildFogHeightTexture();
6801                 // fog color was already set
6802                 // update the fog texture
6803                 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)
6804                         R_BuildFogTexture();
6805                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6806                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6807         }
6808         else
6809                 r_refdef.fogenabled = false;
6810
6811         // fog color
6812         if (r_refdef.fog_density)
6813         {
6814                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6815                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6816                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6817
6818                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6819                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6820                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6821                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6822
6823                 {
6824                         vec3_t fogvec;
6825                         VectorCopy(r_refdef.fogcolor, fogvec);
6826                         //   color.rgb *= ContrastBoost * SceneBrightness;
6827                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6828                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6829                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6830                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6831                 }
6832         }
6833 }
6834
6835 void R_UpdateVariables(void)
6836 {
6837         R_Textures_Frame();
6838
6839         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6840
6841         r_refdef.farclip = r_farclip_base.value;
6842         if (r_refdef.scene.worldmodel)
6843                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6844         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6845
6846         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6847                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6848         r_refdef.polygonfactor = 0;
6849         r_refdef.polygonoffset = 0;
6850         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6851         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6852
6853         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6854         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6855         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6856         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6857         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6858         if (FAKELIGHT_ENABLED)
6859         {
6860                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6861         }
6862         else if (r_refdef.scene.worldmodel)
6863         {
6864                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6865         }
6866         if (r_showsurfaces.integer)
6867         {
6868                 r_refdef.scene.rtworld = false;
6869                 r_refdef.scene.rtworldshadows = false;
6870                 r_refdef.scene.rtdlight = false;
6871                 r_refdef.scene.rtdlightshadows = false;
6872                 r_refdef.lightmapintensity = 0;
6873         }
6874
6875         switch(vid.renderpath)
6876         {
6877         case RENDERPATH_GL20:
6878         case RENDERPATH_D3D9:
6879         case RENDERPATH_D3D10:
6880         case RENDERPATH_D3D11:
6881         case RENDERPATH_SOFT:
6882         case RENDERPATH_GLES2:
6883                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6884                 {
6885                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6886                         {
6887                                 // build GLSL gamma texture
6888 #define RAMPWIDTH 256
6889                                 unsigned short ramp[RAMPWIDTH * 3];
6890                                 unsigned char rampbgr[RAMPWIDTH][4];
6891                                 int i;
6892
6893                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6894
6895                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6896                                 for(i = 0; i < RAMPWIDTH; ++i)
6897                                 {
6898                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6899                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6900                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6901                                         rampbgr[i][3] = 0;
6902                                 }
6903                                 if (r_texture_gammaramps)
6904                                 {
6905                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6906                                 }
6907                                 else
6908                                 {
6909                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6910                                 }
6911                         }
6912                 }
6913                 else
6914                 {
6915                         // remove GLSL gamma texture
6916                 }
6917                 break;
6918         case RENDERPATH_GL11:
6919         case RENDERPATH_GL13:
6920         case RENDERPATH_GLES1:
6921                 break;
6922         }
6923 }
6924
6925 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6926 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6927 /*
6928 ================
6929 R_SelectScene
6930 ================
6931 */
6932 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6933         if( scenetype != r_currentscenetype ) {
6934                 // store the old scenetype
6935                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6936                 r_currentscenetype = scenetype;
6937                 // move in the new scene
6938                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6939         }
6940 }
6941
6942 /*
6943 ================
6944 R_GetScenePointer
6945 ================
6946 */
6947 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6948 {
6949         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6950         if( scenetype == r_currentscenetype ) {
6951                 return &r_refdef.scene;
6952         } else {
6953                 return &r_scenes_store[ scenetype ];
6954         }
6955 }
6956
6957 static int R_SortEntities_Compare(const void *ap, const void *bp)
6958 {
6959         const entity_render_t *a = *(const entity_render_t **)ap;
6960         const entity_render_t *b = *(const entity_render_t **)bp;
6961
6962         // 1. compare model
6963         if(a->model < b->model)
6964                 return -1;
6965         if(a->model > b->model)
6966                 return +1;
6967
6968         // 2. compare skin
6969         // TODO possibly calculate the REAL skinnum here first using
6970         // skinscenes?
6971         if(a->skinnum < b->skinnum)
6972                 return -1;
6973         if(a->skinnum > b->skinnum)
6974                 return +1;
6975
6976         // everything we compared is equal
6977         return 0;
6978 }
6979 static void R_SortEntities(void)
6980 {
6981         // below or equal 2 ents, sorting never gains anything
6982         if(r_refdef.scene.numentities <= 2)
6983                 return;
6984         // sort
6985         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6986 }
6987
6988 /*
6989 ================
6990 R_RenderView
6991 ================
6992 */
6993 int dpsoftrast_test;
6994 extern cvar_t r_shadow_bouncegrid;
6995 void R_RenderView(void)
6996 {
6997         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6998         int fbo;
6999         rtexture_t *depthtexture;
7000         rtexture_t *colortexture;
7001
7002         dpsoftrast_test = r_test.integer;
7003
7004         if (r_timereport_active)
7005                 R_TimeReport("start");
7006         r_textureframe++; // used only by R_GetCurrentTexture
7007         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7008
7009         if(R_CompileShader_CheckStaticParms())
7010                 R_GLSL_Restart_f();
7011
7012         if (!r_drawentities.integer)
7013                 r_refdef.scene.numentities = 0;
7014         else if (r_sortentities.integer)
7015                 R_SortEntities();
7016
7017         R_AnimCache_ClearCache();
7018         R_FrameData_NewFrame();
7019
7020         /* adjust for stereo display */
7021         if(R_Stereo_Active())
7022         {
7023                 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);
7024                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7025         }
7026
7027         if (r_refdef.view.isoverlay)
7028         {
7029                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7030                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7031                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7032                 R_TimeReport("depthclear");
7033
7034                 r_refdef.view.showdebug = false;
7035
7036                 r_fb.water.enabled = false;
7037                 r_fb.water.numwaterplanes = 0;
7038
7039                 R_RenderScene(0, NULL, NULL);
7040
7041                 r_refdef.view.matrix = originalmatrix;
7042
7043                 CHECKGLERROR
7044                 return;
7045         }
7046
7047         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7048         {
7049                 r_refdef.view.matrix = originalmatrix;
7050                 return;
7051         }
7052
7053         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7054
7055         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7056                 // in sRGB fallback, behave similar to true sRGB: convert this
7057                 // value from linear to sRGB
7058                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7059
7060         R_RenderView_UpdateViewVectors();
7061
7062         R_Shadow_UpdateWorldLightSelection();
7063
7064         R_Bloom_StartFrame();
7065
7066         // apply bloom brightness offset
7067         if(r_fb.bloomtexture[0])
7068                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7069
7070         R_Water_StartFrame();
7071
7072         // now we probably have an fbo to render into
7073         fbo = r_fb.fbo;
7074         depthtexture = r_fb.depthtexture;
7075         colortexture = r_fb.colortexture;
7076
7077         CHECKGLERROR
7078         if (r_timereport_active)
7079                 R_TimeReport("viewsetup");
7080
7081         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7082
7083         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7084         {
7085                 R_ClearScreen(r_refdef.fogenabled);
7086                 if (r_timereport_active)
7087                         R_TimeReport("viewclear");
7088         }
7089         r_refdef.view.clear = true;
7090
7091         r_refdef.view.showdebug = true;
7092
7093         R_View_Update();
7094         if (r_timereport_active)
7095                 R_TimeReport("visibility");
7096
7097         R_AnimCache_CacheVisibleEntities();
7098         if (r_timereport_active)
7099                 R_TimeReport("animcache");
7100
7101         R_Shadow_UpdateBounceGridTexture();
7102         if (r_timereport_active && r_shadow_bouncegrid.integer)
7103                 R_TimeReport("bouncegrid");
7104
7105         r_fb.water.numwaterplanes = 0;
7106         if (r_fb.water.enabled)
7107                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7108
7109         R_RenderScene(fbo, depthtexture, colortexture);
7110         r_fb.water.numwaterplanes = 0;
7111
7112         R_BlendView(fbo, depthtexture, colortexture);
7113         if (r_timereport_active)
7114                 R_TimeReport("blendview");
7115
7116         GL_Scissor(0, 0, vid.width, vid.height);
7117         GL_ScissorTest(false);
7118
7119         r_refdef.view.matrix = originalmatrix;
7120
7121         CHECKGLERROR
7122 }
7123
7124 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7125 {
7126         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7127         {
7128                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7129                 if (r_timereport_active)
7130                         R_TimeReport("waterworld");
7131         }
7132
7133         // don't let sound skip if going slow
7134         if (r_refdef.scene.extraupdate)
7135                 S_ExtraUpdate ();
7136
7137         R_DrawModelsAddWaterPlanes();
7138         if (r_timereport_active)
7139                 R_TimeReport("watermodels");
7140
7141         if (r_fb.water.numwaterplanes)
7142         {
7143                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7144                 if (r_timereport_active)
7145                         R_TimeReport("waterscenes");
7146         }
7147 }
7148
7149 extern cvar_t cl_locs_show;
7150 static void R_DrawLocs(void);
7151 static void R_DrawEntityBBoxes(void);
7152 static void R_DrawModelDecals(void);
7153 extern cvar_t cl_decals_newsystem;
7154 extern qboolean r_shadow_usingdeferredprepass;
7155 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7156 {
7157         qboolean shadowmapping = false;
7158
7159         if (r_timereport_active)
7160                 R_TimeReport("beginscene");
7161
7162         r_refdef.stats.renders++;
7163
7164         R_UpdateFog();
7165
7166         // don't let sound skip if going slow
7167         if (r_refdef.scene.extraupdate)
7168                 S_ExtraUpdate ();
7169
7170         R_MeshQueue_BeginScene();
7171
7172         R_SkyStartFrame();
7173
7174         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);
7175
7176         if (r_timereport_active)
7177                 R_TimeReport("skystartframe");
7178
7179         if (cl.csqc_vidvars.drawworld)
7180         {
7181                 // don't let sound skip if going slow
7182                 if (r_refdef.scene.extraupdate)
7183                         S_ExtraUpdate ();
7184
7185                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7186                 {
7187                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7188                         if (r_timereport_active)
7189                                 R_TimeReport("worldsky");
7190                 }
7191
7192                 if (R_DrawBrushModelsSky() && r_timereport_active)
7193                         R_TimeReport("bmodelsky");
7194
7195                 if (skyrendermasked && skyrenderlater)
7196                 {
7197                         // we have to force off the water clipping plane while rendering sky
7198                         R_SetupView(false, fbo, depthtexture, colortexture);
7199                         R_Sky();
7200                         R_SetupView(true, fbo, depthtexture, colortexture);
7201                         if (r_timereport_active)
7202                                 R_TimeReport("sky");
7203                 }
7204         }
7205
7206         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7207         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7208                 R_Shadow_PrepareModelShadows();
7209         if (r_timereport_active)
7210                 R_TimeReport("preparelights");
7211
7212         if (R_Shadow_ShadowMappingEnabled())
7213                 shadowmapping = true;
7214
7215         if (r_shadow_usingdeferredprepass)
7216                 R_Shadow_DrawPrepass();
7217
7218         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7219         {
7220                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7221                 if (r_timereport_active)
7222                         R_TimeReport("worlddepth");
7223         }
7224         if (r_depthfirst.integer >= 2)
7225         {
7226                 R_DrawModelsDepth();
7227                 if (r_timereport_active)
7228                         R_TimeReport("modeldepth");
7229         }
7230
7231         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7232         {
7233                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7234                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7235                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7236                 // don't let sound skip if going slow
7237                 if (r_refdef.scene.extraupdate)
7238                         S_ExtraUpdate ();
7239         }
7240
7241         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7242         {
7243                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7244                 if (r_timereport_active)
7245                         R_TimeReport("world");
7246         }
7247
7248         // don't let sound skip if going slow
7249         if (r_refdef.scene.extraupdate)
7250                 S_ExtraUpdate ();
7251
7252         R_DrawModels();
7253         if (r_timereport_active)
7254                 R_TimeReport("models");
7255
7256         // don't let sound skip if going slow
7257         if (r_refdef.scene.extraupdate)
7258                 S_ExtraUpdate ();
7259
7260         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7261         {
7262                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7263                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7264                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7265                 // don't let sound skip if going slow
7266                 if (r_refdef.scene.extraupdate)
7267                         S_ExtraUpdate ();
7268         }
7269
7270         if (!r_shadow_usingdeferredprepass)
7271         {
7272                 R_Shadow_DrawLights();
7273                 if (r_timereport_active)
7274                         R_TimeReport("rtlights");
7275         }
7276
7277         // don't let sound skip if going slow
7278         if (r_refdef.scene.extraupdate)
7279                 S_ExtraUpdate ();
7280
7281         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7282         {
7283                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7284                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7285                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7286                 // don't let sound skip if going slow
7287                 if (r_refdef.scene.extraupdate)
7288                         S_ExtraUpdate ();
7289         }
7290
7291         if (cl.csqc_vidvars.drawworld)
7292         {
7293                 if (cl_decals_newsystem.integer)
7294                 {
7295                         R_DrawModelDecals();
7296                         if (r_timereport_active)
7297                                 R_TimeReport("modeldecals");
7298                 }
7299                 else
7300                 {
7301                         R_DrawDecals();
7302                         if (r_timereport_active)
7303                                 R_TimeReport("decals");
7304                 }
7305
7306                 R_DrawParticles();
7307                 if (r_timereport_active)
7308                         R_TimeReport("particles");
7309
7310                 R_DrawExplosions();
7311                 if (r_timereport_active)
7312                         R_TimeReport("explosions");
7313
7314                 R_DrawLightningBeams();
7315                 if (r_timereport_active)
7316                         R_TimeReport("lightning");
7317         }
7318
7319         if (cl.csqc_loaded)
7320                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7321
7322         if (r_refdef.view.showdebug)
7323         {
7324                 if (cl_locs_show.integer)
7325                 {
7326                         R_DrawLocs();
7327                         if (r_timereport_active)
7328                                 R_TimeReport("showlocs");
7329                 }
7330
7331                 if (r_drawportals.integer)
7332                 {
7333                         R_DrawPortals();
7334                         if (r_timereport_active)
7335                                 R_TimeReport("portals");
7336                 }
7337
7338                 if (r_showbboxes.value > 0)
7339                 {
7340                         R_DrawEntityBBoxes();
7341                         if (r_timereport_active)
7342                                 R_TimeReport("bboxes");
7343                 }
7344         }
7345
7346         if (r_transparent.integer)
7347         {
7348                 R_MeshQueue_RenderTransparent();
7349                 if (r_timereport_active)
7350                         R_TimeReport("drawtrans");
7351         }
7352
7353         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))
7354         {
7355                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7356                 if (r_timereport_active)
7357                         R_TimeReport("worlddebug");
7358                 R_DrawModelsDebug();
7359                 if (r_timereport_active)
7360                         R_TimeReport("modeldebug");
7361         }
7362
7363         if (cl.csqc_vidvars.drawworld)
7364         {
7365                 R_Shadow_DrawCoronas();
7366                 if (r_timereport_active)
7367                         R_TimeReport("coronas");
7368         }
7369
7370 #if 0
7371         {
7372                 GL_DepthTest(false);
7373                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7374                 GL_Color(1, 1, 1, 1);
7375                 qglBegin(GL_POLYGON);
7376                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7377                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7378                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7379                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7380                 qglEnd();
7381                 qglBegin(GL_POLYGON);
7382                 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]);
7383                 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]);
7384                 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]);
7385                 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]);
7386                 qglEnd();
7387                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7388         }
7389 #endif
7390
7391         // don't let sound skip if going slow
7392         if (r_refdef.scene.extraupdate)
7393                 S_ExtraUpdate ();
7394 }
7395
7396 static const unsigned short bboxelements[36] =
7397 {
7398         5, 1, 3, 5, 3, 7,
7399         6, 2, 0, 6, 0, 4,
7400         7, 3, 2, 7, 2, 6,
7401         4, 0, 1, 4, 1, 5,
7402         4, 5, 7, 4, 7, 6,
7403         1, 0, 2, 1, 2, 3,
7404 };
7405
7406 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7407 {
7408         int i;
7409         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7410
7411         RSurf_ActiveWorldEntity();
7412
7413         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7414         GL_DepthMask(false);
7415         GL_DepthRange(0, 1);
7416         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7417 //      R_Mesh_ResetTextureState();
7418
7419         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7420         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7421         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7422         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7423         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7424         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7425         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7426         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7427         R_FillColors(color4f, 8, cr, cg, cb, ca);
7428         if (r_refdef.fogenabled)
7429         {
7430                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7431                 {
7432                         f1 = RSurf_FogVertex(v);
7433                         f2 = 1 - f1;
7434                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7435                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7436                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7437                 }
7438         }
7439         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7440         R_Mesh_ResetTextureState();
7441         R_SetupShader_Generic_NoTexture(false, false);
7442         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7443 }
7444
7445 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7446 {
7447         prvm_prog_t *prog = SVVM_prog;
7448         int i;
7449         float color[4];
7450         prvm_edict_t *edict;
7451
7452         // this function draws bounding boxes of server entities
7453         if (!sv.active)
7454                 return;
7455
7456         GL_CullFace(GL_NONE);
7457         R_SetupShader_Generic_NoTexture(false, false);
7458
7459         for (i = 0;i < numsurfaces;i++)
7460         {
7461                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7462                 switch ((int)PRVM_serveredictfloat(edict, solid))
7463                 {
7464                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7465                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7466                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7467                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7468                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7469                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7470                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7471                 }
7472                 color[3] *= r_showbboxes.value;
7473                 color[3] = bound(0, color[3], 1);
7474                 GL_DepthTest(!r_showdisabledepthtest.integer);
7475                 GL_CullFace(r_refdef.view.cullface_front);
7476                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7477         }
7478 }
7479
7480 static void R_DrawEntityBBoxes(void)
7481 {
7482         int i;
7483         prvm_edict_t *edict;
7484         vec3_t center;
7485         prvm_prog_t *prog = SVVM_prog;
7486
7487         // this function draws bounding boxes of server entities
7488         if (!sv.active)
7489                 return;
7490
7491         for (i = 0;i < prog->num_edicts;i++)
7492         {
7493                 edict = PRVM_EDICT_NUM(i);
7494                 if (edict->priv.server->free)
7495                         continue;
7496                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7497                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7498                         continue;
7499                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7500                         continue;
7501                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7502                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7503         }
7504 }
7505
7506 static const int nomodelelement3i[24] =
7507 {
7508         5, 2, 0,
7509         5, 1, 2,
7510         5, 0, 3,
7511         5, 3, 1,
7512         0, 2, 4,
7513         2, 1, 4,
7514         3, 0, 4,
7515         1, 3, 4
7516 };
7517
7518 static const unsigned short nomodelelement3s[24] =
7519 {
7520         5, 2, 0,
7521         5, 1, 2,
7522         5, 0, 3,
7523         5, 3, 1,
7524         0, 2, 4,
7525         2, 1, 4,
7526         3, 0, 4,
7527         1, 3, 4
7528 };
7529
7530 static const float nomodelvertex3f[6*3] =
7531 {
7532         -16,   0,   0,
7533          16,   0,   0,
7534           0, -16,   0,
7535           0,  16,   0,
7536           0,   0, -16,
7537           0,   0,  16
7538 };
7539
7540 static const float nomodelcolor4f[6*4] =
7541 {
7542         0.0f, 0.0f, 0.5f, 1.0f,
7543         0.0f, 0.0f, 0.5f, 1.0f,
7544         0.0f, 0.5f, 0.0f, 1.0f,
7545         0.0f, 0.5f, 0.0f, 1.0f,
7546         0.5f, 0.0f, 0.0f, 1.0f,
7547         0.5f, 0.0f, 0.0f, 1.0f
7548 };
7549
7550 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7551 {
7552         int i;
7553         float f1, f2, *c;
7554         float color4f[6*4];
7555
7556         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);
7557
7558         // this is only called once per entity so numsurfaces is always 1, and
7559         // surfacelist is always {0}, so this code does not handle batches
7560
7561         if (rsurface.ent_flags & RENDER_ADDITIVE)
7562         {
7563                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7564                 GL_DepthMask(false);
7565         }
7566         else if (rsurface.colormod[3] < 1)
7567         {
7568                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7569                 GL_DepthMask(false);
7570         }
7571         else
7572         {
7573                 GL_BlendFunc(GL_ONE, GL_ZERO);
7574                 GL_DepthMask(true);
7575         }
7576         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7577         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7578         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7579         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7580         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7581         for (i = 0, c = color4f;i < 6;i++, c += 4)
7582         {
7583                 c[0] *= rsurface.colormod[0];
7584                 c[1] *= rsurface.colormod[1];
7585                 c[2] *= rsurface.colormod[2];
7586                 c[3] *= rsurface.colormod[3];
7587         }
7588         if (r_refdef.fogenabled)
7589         {
7590                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7591                 {
7592                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7593                         f2 = 1 - f1;
7594                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7595                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7596                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7597                 }
7598         }
7599 //      R_Mesh_ResetTextureState();
7600         R_SetupShader_Generic_NoTexture(false, false);
7601         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7602         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7603 }
7604
7605 void R_DrawNoModel(entity_render_t *ent)
7606 {
7607         vec3_t org;
7608         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7609         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7610                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7611         else
7612                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7613 }
7614
7615 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7616 {
7617         vec3_t right1, right2, diff, normal;
7618
7619         VectorSubtract (org2, org1, normal);
7620
7621         // calculate 'right' vector for start
7622         VectorSubtract (r_refdef.view.origin, org1, diff);
7623         CrossProduct (normal, diff, right1);
7624         VectorNormalize (right1);
7625
7626         // calculate 'right' vector for end
7627         VectorSubtract (r_refdef.view.origin, org2, diff);
7628         CrossProduct (normal, diff, right2);
7629         VectorNormalize (right2);
7630
7631         vert[ 0] = org1[0] + width * right1[0];
7632         vert[ 1] = org1[1] + width * right1[1];
7633         vert[ 2] = org1[2] + width * right1[2];
7634         vert[ 3] = org1[0] - width * right1[0];
7635         vert[ 4] = org1[1] - width * right1[1];
7636         vert[ 5] = org1[2] - width * right1[2];
7637         vert[ 6] = org2[0] - width * right2[0];
7638         vert[ 7] = org2[1] - width * right2[1];
7639         vert[ 8] = org2[2] - width * right2[2];
7640         vert[ 9] = org2[0] + width * right2[0];
7641         vert[10] = org2[1] + width * right2[1];
7642         vert[11] = org2[2] + width * right2[2];
7643 }
7644
7645 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)
7646 {
7647         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7648         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7649         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7650         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7651         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7652         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7653         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7654         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7655         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7656         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7657         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7658         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7659 }
7660
7661 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7662 {
7663         int i;
7664         float *vertex3f;
7665         float v[3];
7666         VectorSet(v, x, y, z);
7667         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7668                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7669                         break;
7670         if (i == mesh->numvertices)
7671         {
7672                 if (mesh->numvertices < mesh->maxvertices)
7673                 {
7674                         VectorCopy(v, vertex3f);
7675                         mesh->numvertices++;
7676                 }
7677                 return mesh->numvertices;
7678         }
7679         else
7680                 return i;
7681 }
7682
7683 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7684 {
7685         int i;
7686         int *e, element[3];
7687         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7688         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7689         e = mesh->element3i + mesh->numtriangles * 3;
7690         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7691         {
7692                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7693                 if (mesh->numtriangles < mesh->maxtriangles)
7694                 {
7695                         *e++ = element[0];
7696                         *e++ = element[1];
7697                         *e++ = element[2];
7698                         mesh->numtriangles++;
7699                 }
7700                 element[1] = element[2];
7701         }
7702 }
7703
7704 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7705 {
7706         int i;
7707         int *e, element[3];
7708         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7709         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7710         e = mesh->element3i + mesh->numtriangles * 3;
7711         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7712         {
7713                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7714                 if (mesh->numtriangles < mesh->maxtriangles)
7715                 {
7716                         *e++ = element[0];
7717                         *e++ = element[1];
7718                         *e++ = element[2];
7719                         mesh->numtriangles++;
7720                 }
7721                 element[1] = element[2];
7722         }
7723 }
7724
7725 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7726 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7727 {
7728         int planenum, planenum2;
7729         int w;
7730         int tempnumpoints;
7731         mplane_t *plane, *plane2;
7732         double maxdist;
7733         double temppoints[2][256*3];
7734         // figure out how large a bounding box we need to properly compute this brush
7735         maxdist = 0;
7736         for (w = 0;w < numplanes;w++)
7737                 maxdist = max(maxdist, fabs(planes[w].dist));
7738         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7739         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7740         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7741         {
7742                 w = 0;
7743                 tempnumpoints = 4;
7744                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7745                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7746                 {
7747                         if (planenum2 == planenum)
7748                                 continue;
7749                         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);
7750                         w = !w;
7751                 }
7752                 if (tempnumpoints < 3)
7753                         continue;
7754                 // generate elements forming a triangle fan for this polygon
7755                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7756         }
7757 }
7758
7759 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)
7760 {
7761         texturelayer_t *layer;
7762         layer = t->currentlayers + t->currentnumlayers++;
7763         layer->type = type;
7764         layer->depthmask = depthmask;
7765         layer->blendfunc1 = blendfunc1;
7766         layer->blendfunc2 = blendfunc2;
7767         layer->texture = texture;
7768         layer->texmatrix = *matrix;
7769         layer->color[0] = r;
7770         layer->color[1] = g;
7771         layer->color[2] = b;
7772         layer->color[3] = a;
7773 }
7774
7775 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7776 {
7777         if(parms[0] == 0 && parms[1] == 0)
7778                 return false;
7779         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7780                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7781                         return false;
7782         return true;
7783 }
7784
7785 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7786 {
7787         double index, f;
7788         index = parms[2] + rsurface.shadertime * parms[3];
7789         index -= floor(index);
7790         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7791         {
7792         default:
7793         case Q3WAVEFUNC_NONE:
7794         case Q3WAVEFUNC_NOISE:
7795         case Q3WAVEFUNC_COUNT:
7796                 f = 0;
7797                 break;
7798         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7799         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7800         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7801         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7802         case Q3WAVEFUNC_TRIANGLE:
7803                 index *= 4;
7804                 f = index - floor(index);
7805                 if (index < 1)
7806                 {
7807                         // f = f;
7808                 }
7809                 else if (index < 2)
7810                         f = 1 - f;
7811                 else if (index < 3)
7812                         f = -f;
7813                 else
7814                         f = -(1 - f);
7815                 break;
7816         }
7817         f = parms[0] + parms[1] * f;
7818         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7819                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7820         return (float) f;
7821 }
7822
7823 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7824 {
7825         int w, h, idx;
7826         double f;
7827         double offsetd[2];
7828         float tcmat[12];
7829         matrix4x4_t matrix, temp;
7830         switch(tcmod->tcmod)
7831         {
7832                 case Q3TCMOD_COUNT:
7833                 case Q3TCMOD_NONE:
7834                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7835                                 matrix = r_waterscrollmatrix;
7836                         else
7837                                 matrix = identitymatrix;
7838                         break;
7839                 case Q3TCMOD_ENTITYTRANSLATE:
7840                         // this is used in Q3 to allow the gamecode to control texcoord
7841                         // scrolling on the entity, which is not supported in darkplaces yet.
7842                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7843                         break;
7844                 case Q3TCMOD_ROTATE:
7845                         f = tcmod->parms[0] * rsurface.shadertime;
7846                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7847                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7848                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7849                         break;
7850                 case Q3TCMOD_SCALE:
7851                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7852                         break;
7853                 case Q3TCMOD_SCROLL:
7854                         // extra care is needed because of precision breakdown with large values of time
7855                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7856                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7857                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7858                         break;
7859                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7860                         w = (int) tcmod->parms[0];
7861                         h = (int) tcmod->parms[1];
7862                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7863                         f = f - floor(f);
7864                         idx = (int) floor(f * w * h);
7865                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7866                         break;
7867                 case Q3TCMOD_STRETCH:
7868                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7869                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7870                         break;
7871                 case Q3TCMOD_TRANSFORM:
7872                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7873                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7874                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7875                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7876                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7877                         break;
7878                 case Q3TCMOD_TURBULENT:
7879                         // this is handled in the RSurf_PrepareVertices function
7880                         matrix = identitymatrix;
7881                         break;
7882         }
7883         temp = *texmatrix;
7884         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7885 }
7886
7887 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7888 {
7889         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7890         char name[MAX_QPATH];
7891         skinframe_t *skinframe;
7892         unsigned char pixels[296*194];
7893         strlcpy(cache->name, skinname, sizeof(cache->name));
7894         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7895         if (developer_loading.integer)
7896                 Con_Printf("loading %s\n", name);
7897         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7898         if (!skinframe || !skinframe->base)
7899         {
7900                 unsigned char *f;
7901                 fs_offset_t filesize;
7902                 skinframe = NULL;
7903                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7904                 if (f)
7905                 {
7906                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7907                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7908                         Mem_Free(f);
7909                 }
7910         }
7911         cache->skinframe = skinframe;
7912 }
7913
7914 texture_t *R_GetCurrentTexture(texture_t *t)
7915 {
7916         int i;
7917         const entity_render_t *ent = rsurface.entity;
7918         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7919         q3shaderinfo_layer_tcmod_t *tcmod;
7920
7921         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7922                 return t->currentframe;
7923         t->update_lastrenderframe = r_textureframe;
7924         t->update_lastrenderentity = (void *)ent;
7925
7926         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7927                 t->camera_entity = ent->entitynumber;
7928         else
7929                 t->camera_entity = 0;
7930
7931         // switch to an alternate material if this is a q1bsp animated material
7932         {
7933                 texture_t *texture = t;
7934                 int s = rsurface.ent_skinnum;
7935                 if ((unsigned int)s >= (unsigned int)model->numskins)
7936                         s = 0;
7937                 if (model->skinscenes)
7938                 {
7939                         if (model->skinscenes[s].framecount > 1)
7940                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7941                         else
7942                                 s = model->skinscenes[s].firstframe;
7943                 }
7944                 if (s > 0)
7945                         t = t + s * model->num_surfaces;
7946                 if (t->animated)
7947                 {
7948                         // use an alternate animation if the entity's frame is not 0,
7949                         // and only if the texture has an alternate animation
7950                         if (rsurface.ent_alttextures && t->anim_total[1])
7951                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7952                         else
7953                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7954                 }
7955                 texture->currentframe = t;
7956         }
7957
7958         // update currentskinframe to be a qw skin or animation frame
7959         if (rsurface.ent_qwskin >= 0)
7960         {
7961                 i = rsurface.ent_qwskin;
7962                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7963                 {
7964                         r_qwskincache_size = cl.maxclients;
7965                         if (r_qwskincache)
7966                                 Mem_Free(r_qwskincache);
7967                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7968                 }
7969                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7970                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7971                 t->currentskinframe = r_qwskincache[i].skinframe;
7972                 if (t->currentskinframe == NULL)
7973                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7974         }
7975         else if (t->numskinframes >= 2)
7976                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7977         if (t->backgroundnumskinframes >= 2)
7978                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7979
7980         t->currentmaterialflags = t->basematerialflags;
7981         t->currentalpha = rsurface.colormod[3];
7982         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7983                 t->currentalpha *= r_wateralpha.value;
7984         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7985                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7986         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7987                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7988         if (!(rsurface.ent_flags & RENDER_LIGHT))
7989                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7990         else if (FAKELIGHT_ENABLED)
7991         {
7992                 // no modellight if using fakelight for the map
7993         }
7994         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7995         {
7996                 // pick a model lighting mode
7997                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7998                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7999                 else
8000                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8001         }
8002         if (rsurface.ent_flags & RENDER_ADDITIVE)
8003                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8004         else if (t->currentalpha < 1)
8005                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8006         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8007         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8008                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8009         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8010                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8011         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8012                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8013         if (t->backgroundnumskinframes)
8014                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8015         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8016         {
8017                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8018                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8019         }
8020         else
8021                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8022         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8023         {
8024                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8025                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8026         }
8027         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8028                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8029
8030         // there is no tcmod
8031         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8032         {
8033                 t->currenttexmatrix = r_waterscrollmatrix;
8034                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8035         }
8036         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8037         {
8038                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8039                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8040         }
8041
8042         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8043                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8044         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8045                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8046
8047         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8048         if (t->currentskinframe->qpixels)
8049                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8050         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8051         if (!t->basetexture)
8052                 t->basetexture = r_texture_notexture;
8053         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8054         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8055         t->nmaptexture = t->currentskinframe->nmap;
8056         if (!t->nmaptexture)
8057                 t->nmaptexture = r_texture_blanknormalmap;
8058         t->glosstexture = r_texture_black;
8059         t->glowtexture = t->currentskinframe->glow;
8060         t->fogtexture = t->currentskinframe->fog;
8061         t->reflectmasktexture = t->currentskinframe->reflect;
8062         if (t->backgroundnumskinframes)
8063         {
8064                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8065                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8066                 t->backgroundglosstexture = r_texture_black;
8067                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8068                 if (!t->backgroundnmaptexture)
8069                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8070                 // make sure that if glow is going to be used, both textures are not NULL
8071                 if (!t->backgroundglowtexture && t->glowtexture)
8072                         t->backgroundglowtexture = r_texture_black;
8073                 if (!t->glowtexture && t->backgroundglowtexture)
8074                         t->glowtexture = r_texture_black;
8075         }
8076         else
8077         {
8078                 t->backgroundbasetexture = r_texture_white;
8079                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8080                 t->backgroundglosstexture = r_texture_black;
8081                 t->backgroundglowtexture = NULL;
8082         }
8083         t->specularpower = r_shadow_glossexponent.value;
8084         // TODO: store reference values for these in the texture?
8085         t->specularscale = 0;
8086         if (r_shadow_gloss.integer > 0)
8087         {
8088                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8089                 {
8090                         if (r_shadow_glossintensity.value > 0)
8091                         {
8092                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8093                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8094                                 t->specularscale = r_shadow_glossintensity.value;
8095                         }
8096                 }
8097                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8098                 {
8099                         t->glosstexture = r_texture_white;
8100                         t->backgroundglosstexture = r_texture_white;
8101                         t->specularscale = r_shadow_gloss2intensity.value;
8102                         t->specularpower = r_shadow_gloss2exponent.value;
8103                 }
8104         }
8105         t->specularscale *= t->specularscalemod;
8106         t->specularpower *= t->specularpowermod;
8107         t->rtlightambient = 0;
8108
8109         // lightmaps mode looks bad with dlights using actual texturing, so turn
8110         // off the colormap and glossmap, but leave the normalmap on as it still
8111         // accurately represents the shading involved
8112         if (gl_lightmaps.integer)
8113         {
8114                 t->basetexture = r_texture_grey128;
8115                 t->pantstexture = r_texture_black;
8116                 t->shirttexture = r_texture_black;
8117                 if (gl_lightmaps.integer < 2)
8118                         t->nmaptexture = r_texture_blanknormalmap;
8119                 t->glosstexture = r_texture_black;
8120                 t->glowtexture = NULL;
8121                 t->fogtexture = NULL;
8122                 t->reflectmasktexture = NULL;
8123                 t->backgroundbasetexture = NULL;
8124                 if (gl_lightmaps.integer < 2)
8125                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8126                 t->backgroundglosstexture = r_texture_black;
8127                 t->backgroundglowtexture = NULL;
8128                 t->specularscale = 0;
8129                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8130         }
8131
8132         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8133         VectorClear(t->dlightcolor);
8134         t->currentnumlayers = 0;
8135         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8136         {
8137                 int blendfunc1, blendfunc2;
8138                 qboolean depthmask;
8139                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8140                 {
8141                         blendfunc1 = GL_SRC_ALPHA;
8142                         blendfunc2 = GL_ONE;
8143                 }
8144                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8145                 {
8146                         blendfunc1 = GL_SRC_ALPHA;
8147                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8148                 }
8149                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8150                 {
8151                         blendfunc1 = t->customblendfunc[0];
8152                         blendfunc2 = t->customblendfunc[1];
8153                 }
8154                 else
8155                 {
8156                         blendfunc1 = GL_ONE;
8157                         blendfunc2 = GL_ZERO;
8158                 }
8159                 // don't colormod evilblend textures
8160                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8161                         VectorSet(t->lightmapcolor, 1, 1, 1);
8162                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8163                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8164                 {
8165                         // fullbright is not affected by r_refdef.lightmapintensity
8166                         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]);
8167                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8168                                 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]);
8169                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8170                                 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]);
8171                 }
8172                 else
8173                 {
8174                         vec3_t ambientcolor;
8175                         float colorscale;
8176                         // set the color tint used for lights affecting this surface
8177                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8178                         colorscale = 2;
8179                         // q3bsp has no lightmap updates, so the lightstylevalue that
8180                         // would normally be baked into the lightmap must be
8181                         // applied to the color
8182                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8183                         if (model->type == mod_brushq3)
8184                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8185                         colorscale *= r_refdef.lightmapintensity;
8186                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8187                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8188                         // basic lit geometry
8189                         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]);
8190                         // add pants/shirt if needed
8191                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8192                                 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]);
8193                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8194                                 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]);
8195                         // now add ambient passes if needed
8196                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8197                         {
8198                                 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]);
8199                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8200                                         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]);
8201                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8202                                         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]);
8203                         }
8204                 }
8205                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8206                         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]);
8207                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8208                 {
8209                         // if this is opaque use alpha blend which will darken the earlier
8210                         // passes cheaply.
8211                         //
8212                         // if this is an alpha blended material, all the earlier passes
8213                         // were darkened by fog already, so we only need to add the fog
8214                         // color ontop through the fog mask texture
8215                         //
8216                         // if this is an additive blended material, all the earlier passes
8217                         // were darkened by fog already, and we should not add fog color
8218                         // (because the background was not darkened, there is no fog color
8219                         // that was lost behind it).
8220                         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]);
8221                 }
8222         }
8223
8224         return t->currentframe;
8225 }
8226
8227 rsurfacestate_t rsurface;
8228
8229 void RSurf_ActiveWorldEntity(void)
8230 {
8231         dp_model_t *model = r_refdef.scene.worldmodel;
8232         //if (rsurface.entity == r_refdef.scene.worldentity)
8233         //      return;
8234         rsurface.entity = r_refdef.scene.worldentity;
8235         rsurface.skeleton = NULL;
8236         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8237         rsurface.ent_skinnum = 0;
8238         rsurface.ent_qwskin = -1;
8239         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8240         rsurface.shadertime = r_refdef.scene.time;
8241         rsurface.matrix = identitymatrix;
8242         rsurface.inversematrix = identitymatrix;
8243         rsurface.matrixscale = 1;
8244         rsurface.inversematrixscale = 1;
8245         R_EntityMatrix(&identitymatrix);
8246         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8247         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8248         rsurface.fograngerecip = r_refdef.fograngerecip;
8249         rsurface.fogheightfade = r_refdef.fogheightfade;
8250         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8251         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8252         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8253         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8254         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8255         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8256         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8257         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8258         rsurface.colormod[3] = 1;
8259         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);
8260         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8261         rsurface.frameblend[0].lerp = 1;
8262         rsurface.ent_alttextures = false;
8263         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8264         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8265         rsurface.entityskeletaltransform3x4 = NULL;
8266         rsurface.entityskeletalnumtransforms = 0;
8267         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8268         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8269         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8270         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8271         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8272         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8273         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8274         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8275         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8276         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8277         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8278         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8279         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8280         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8281         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8282         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8283         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8284         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8285         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8286         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8287         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8288         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8289         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8290         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8291         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8292         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8293         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8294         rsurface.modelelement3i = model->surfmesh.data_element3i;
8295         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8296         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8297         rsurface.modelelement3s = model->surfmesh.data_element3s;
8298         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8299         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8300         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8301         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8302         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8303         rsurface.modelsurfaces = model->data_surfaces;
8304         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8305         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8306         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8307         rsurface.modelgeneratedvertex = false;
8308         rsurface.batchgeneratedvertex = false;
8309         rsurface.batchfirstvertex = 0;
8310         rsurface.batchnumvertices = 0;
8311         rsurface.batchfirsttriangle = 0;
8312         rsurface.batchnumtriangles = 0;
8313         rsurface.batchvertex3f  = NULL;
8314         rsurface.batchvertex3f_vertexbuffer = NULL;
8315         rsurface.batchvertex3f_bufferoffset = 0;
8316         rsurface.batchsvector3f = NULL;
8317         rsurface.batchsvector3f_vertexbuffer = NULL;
8318         rsurface.batchsvector3f_bufferoffset = 0;
8319         rsurface.batchtvector3f = NULL;
8320         rsurface.batchtvector3f_vertexbuffer = NULL;
8321         rsurface.batchtvector3f_bufferoffset = 0;
8322         rsurface.batchnormal3f  = NULL;
8323         rsurface.batchnormal3f_vertexbuffer = NULL;
8324         rsurface.batchnormal3f_bufferoffset = 0;
8325         rsurface.batchlightmapcolor4f = NULL;
8326         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8327         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8328         rsurface.batchtexcoordtexture2f = NULL;
8329         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8330         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8331         rsurface.batchtexcoordlightmap2f = NULL;
8332         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8333         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8334         rsurface.batchskeletalindex4ub = NULL;
8335         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8336         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8337         rsurface.batchskeletalweight4ub = NULL;
8338         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8339         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8340         rsurface.batchvertexmesh = NULL;
8341         rsurface.batchvertexmeshbuffer = NULL;
8342         rsurface.batchvertex3fbuffer = NULL;
8343         rsurface.batchelement3i = NULL;
8344         rsurface.batchelement3i_indexbuffer = NULL;
8345         rsurface.batchelement3i_bufferoffset = 0;
8346         rsurface.batchelement3s = NULL;
8347         rsurface.batchelement3s_indexbuffer = NULL;
8348         rsurface.batchelement3s_bufferoffset = 0;
8349         rsurface.passcolor4f = NULL;
8350         rsurface.passcolor4f_vertexbuffer = NULL;
8351         rsurface.passcolor4f_bufferoffset = 0;
8352         rsurface.forcecurrenttextureupdate = false;
8353 }
8354
8355 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8356 {
8357         dp_model_t *model = ent->model;
8358         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8359         //      return;
8360         rsurface.entity = (entity_render_t *)ent;
8361         rsurface.skeleton = ent->skeleton;
8362         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8363         rsurface.ent_skinnum = ent->skinnum;
8364         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;
8365         rsurface.ent_flags = ent->flags;
8366         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8367         rsurface.matrix = ent->matrix;
8368         rsurface.inversematrix = ent->inversematrix;
8369         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8370         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8371         R_EntityMatrix(&rsurface.matrix);
8372         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8373         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8374         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8375         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8376         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8377         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8378         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8379         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8380         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8381         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8382         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8383         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8384         rsurface.colormod[3] = ent->alpha;
8385         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8386         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8387         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8388         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8389         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8390         if (ent->model->brush.submodel && !prepass)
8391         {
8392                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8393                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8394         }
8395         // if the animcache code decided it should use the shader path, skip the deform step
8396         rsurface.entityskeletaltransform3x4 = ent->animcache_vertex3f ? NULL : ent->animcache_skeletaltransform3x4;
8397         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8398         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8399         {
8400                 if (ent->animcache_vertex3f)
8401                 {
8402                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8403                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8404                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8405                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8406                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8407                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8408                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8409                 }
8410                 else if (wanttangents)
8411                 {
8412                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8413                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8414                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8415                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8416                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8417                         rsurface.modelvertexmesh = NULL;
8418                         rsurface.modelvertexmeshbuffer = NULL;
8419                         rsurface.modelvertex3fbuffer = NULL;
8420                 }
8421                 else if (wantnormals)
8422                 {
8423                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8424                         rsurface.modelsvector3f = NULL;
8425                         rsurface.modeltvector3f = NULL;
8426                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8427                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8428                         rsurface.modelvertexmesh = NULL;
8429                         rsurface.modelvertexmeshbuffer = NULL;
8430                         rsurface.modelvertex3fbuffer = NULL;
8431                 }
8432                 else
8433                 {
8434                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8435                         rsurface.modelsvector3f = NULL;
8436                         rsurface.modeltvector3f = NULL;
8437                         rsurface.modelnormal3f = NULL;
8438                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8439                         rsurface.modelvertexmesh = NULL;
8440                         rsurface.modelvertexmeshbuffer = NULL;
8441                         rsurface.modelvertex3fbuffer = NULL;
8442                 }
8443                 rsurface.modelvertex3f_vertexbuffer = 0;
8444                 rsurface.modelvertex3f_bufferoffset = 0;
8445                 rsurface.modelsvector3f_vertexbuffer = 0;
8446                 rsurface.modelsvector3f_bufferoffset = 0;
8447                 rsurface.modeltvector3f_vertexbuffer = 0;
8448                 rsurface.modeltvector3f_bufferoffset = 0;
8449                 rsurface.modelnormal3f_vertexbuffer = 0;
8450                 rsurface.modelnormal3f_bufferoffset = 0;
8451                 rsurface.modelgeneratedvertex = true;
8452         }
8453         else
8454         {
8455                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8456                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8457                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8458                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8459                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8460                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8461                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8462                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8463                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8464                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8465                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8466                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8467                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8468                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8469                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8470                 rsurface.modelgeneratedvertex = false;
8471         }
8472         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8473         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8474         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8475         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8476         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8477         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8478         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8479         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8480         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8481         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8482         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8483         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8484         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8485         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8486         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8487         rsurface.modelelement3i = model->surfmesh.data_element3i;
8488         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8489         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8490         rsurface.modelelement3s = model->surfmesh.data_element3s;
8491         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8492         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8493         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8494         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8495         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8496         rsurface.modelsurfaces = model->data_surfaces;
8497         rsurface.batchgeneratedvertex = false;
8498         rsurface.batchfirstvertex = 0;
8499         rsurface.batchnumvertices = 0;
8500         rsurface.batchfirsttriangle = 0;
8501         rsurface.batchnumtriangles = 0;
8502         rsurface.batchvertex3f  = NULL;
8503         rsurface.batchvertex3f_vertexbuffer = NULL;
8504         rsurface.batchvertex3f_bufferoffset = 0;
8505         rsurface.batchsvector3f = NULL;
8506         rsurface.batchsvector3f_vertexbuffer = NULL;
8507         rsurface.batchsvector3f_bufferoffset = 0;
8508         rsurface.batchtvector3f = NULL;
8509         rsurface.batchtvector3f_vertexbuffer = NULL;
8510         rsurface.batchtvector3f_bufferoffset = 0;
8511         rsurface.batchnormal3f  = NULL;
8512         rsurface.batchnormal3f_vertexbuffer = NULL;
8513         rsurface.batchnormal3f_bufferoffset = 0;
8514         rsurface.batchlightmapcolor4f = NULL;
8515         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8516         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8517         rsurface.batchtexcoordtexture2f = NULL;
8518         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8519         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8520         rsurface.batchtexcoordlightmap2f = NULL;
8521         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8522         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8523         rsurface.batchskeletalindex4ub = NULL;
8524         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8525         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8526         rsurface.batchskeletalweight4ub = NULL;
8527         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8528         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8529         rsurface.batchvertexmesh = NULL;
8530         rsurface.batchvertexmeshbuffer = NULL;
8531         rsurface.batchvertex3fbuffer = NULL;
8532         rsurface.batchelement3i = NULL;
8533         rsurface.batchelement3i_indexbuffer = NULL;
8534         rsurface.batchelement3i_bufferoffset = 0;
8535         rsurface.batchelement3s = NULL;
8536         rsurface.batchelement3s_indexbuffer = NULL;
8537         rsurface.batchelement3s_bufferoffset = 0;
8538         rsurface.passcolor4f = NULL;
8539         rsurface.passcolor4f_vertexbuffer = NULL;
8540         rsurface.passcolor4f_bufferoffset = 0;
8541         rsurface.forcecurrenttextureupdate = false;
8542 }
8543
8544 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)
8545 {
8546         rsurface.entity = r_refdef.scene.worldentity;
8547         rsurface.skeleton = NULL;
8548         rsurface.ent_skinnum = 0;
8549         rsurface.ent_qwskin = -1;
8550         rsurface.ent_flags = entflags;
8551         rsurface.shadertime = r_refdef.scene.time - shadertime;
8552         rsurface.modelnumvertices = numvertices;
8553         rsurface.modelnumtriangles = numtriangles;
8554         rsurface.matrix = *matrix;
8555         rsurface.inversematrix = *inversematrix;
8556         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8557         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8558         R_EntityMatrix(&rsurface.matrix);
8559         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8560         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8561         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8562         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8563         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8564         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8565         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8566         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8567         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8568         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8569         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8570         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8571         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);
8572         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8573         rsurface.frameblend[0].lerp = 1;
8574         rsurface.ent_alttextures = false;
8575         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8576         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8577         rsurface.entityskeletaltransform3x4 = NULL;
8578         rsurface.entityskeletalnumtransforms = 0;
8579         if (wanttangents)
8580         {
8581                 rsurface.modelvertex3f = (float *)vertex3f;
8582                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8583                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8584                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8585         }
8586         else if (wantnormals)
8587         {
8588                 rsurface.modelvertex3f = (float *)vertex3f;
8589                 rsurface.modelsvector3f = NULL;
8590                 rsurface.modeltvector3f = NULL;
8591                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8592         }
8593         else
8594         {
8595                 rsurface.modelvertex3f = (float *)vertex3f;
8596                 rsurface.modelsvector3f = NULL;
8597                 rsurface.modeltvector3f = NULL;
8598                 rsurface.modelnormal3f = NULL;
8599         }
8600         rsurface.modelvertexmesh = NULL;
8601         rsurface.modelvertexmeshbuffer = NULL;
8602         rsurface.modelvertex3fbuffer = NULL;
8603         rsurface.modelvertex3f_vertexbuffer = 0;
8604         rsurface.modelvertex3f_bufferoffset = 0;
8605         rsurface.modelsvector3f_vertexbuffer = 0;
8606         rsurface.modelsvector3f_bufferoffset = 0;
8607         rsurface.modeltvector3f_vertexbuffer = 0;
8608         rsurface.modeltvector3f_bufferoffset = 0;
8609         rsurface.modelnormal3f_vertexbuffer = 0;
8610         rsurface.modelnormal3f_bufferoffset = 0;
8611         rsurface.modelgeneratedvertex = true;
8612         rsurface.modellightmapcolor4f  = (float *)color4f;
8613         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8614         rsurface.modellightmapcolor4f_bufferoffset = 0;
8615         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8616         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8617         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8618         rsurface.modeltexcoordlightmap2f  = NULL;
8619         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8620         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8621         rsurface.modelskeletalindex4ub = NULL;
8622         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8623         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8624         rsurface.modelskeletalweight4ub = NULL;
8625         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8626         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8627         rsurface.modelelement3i = (int *)element3i;
8628         rsurface.modelelement3i_indexbuffer = NULL;
8629         rsurface.modelelement3i_bufferoffset = 0;
8630         rsurface.modelelement3s = (unsigned short *)element3s;
8631         rsurface.modelelement3s_indexbuffer = NULL;
8632         rsurface.modelelement3s_bufferoffset = 0;
8633         rsurface.modellightmapoffsets = NULL;
8634         rsurface.modelsurfaces = NULL;
8635         rsurface.batchgeneratedvertex = false;
8636         rsurface.batchfirstvertex = 0;
8637         rsurface.batchnumvertices = 0;
8638         rsurface.batchfirsttriangle = 0;
8639         rsurface.batchnumtriangles = 0;
8640         rsurface.batchvertex3f  = NULL;
8641         rsurface.batchvertex3f_vertexbuffer = NULL;
8642         rsurface.batchvertex3f_bufferoffset = 0;
8643         rsurface.batchsvector3f = NULL;
8644         rsurface.batchsvector3f_vertexbuffer = NULL;
8645         rsurface.batchsvector3f_bufferoffset = 0;
8646         rsurface.batchtvector3f = NULL;
8647         rsurface.batchtvector3f_vertexbuffer = NULL;
8648         rsurface.batchtvector3f_bufferoffset = 0;
8649         rsurface.batchnormal3f  = NULL;
8650         rsurface.batchnormal3f_vertexbuffer = NULL;
8651         rsurface.batchnormal3f_bufferoffset = 0;
8652         rsurface.batchlightmapcolor4f = NULL;
8653         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8654         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8655         rsurface.batchtexcoordtexture2f = NULL;
8656         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8657         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8658         rsurface.batchtexcoordlightmap2f = NULL;
8659         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8660         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8661         rsurface.batchskeletalindex4ub = NULL;
8662         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8663         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8664         rsurface.batchskeletalweight4ub = NULL;
8665         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8666         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8667         rsurface.batchvertexmesh = NULL;
8668         rsurface.batchvertexmeshbuffer = NULL;
8669         rsurface.batchvertex3fbuffer = NULL;
8670         rsurface.batchelement3i = NULL;
8671         rsurface.batchelement3i_indexbuffer = NULL;
8672         rsurface.batchelement3i_bufferoffset = 0;
8673         rsurface.batchelement3s = NULL;
8674         rsurface.batchelement3s_indexbuffer = NULL;
8675         rsurface.batchelement3s_bufferoffset = 0;
8676         rsurface.passcolor4f = NULL;
8677         rsurface.passcolor4f_vertexbuffer = NULL;
8678         rsurface.passcolor4f_bufferoffset = 0;
8679         rsurface.forcecurrenttextureupdate = true;
8680
8681         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8682         {
8683                 if ((wantnormals || wanttangents) && !normal3f)
8684                 {
8685                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8686                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8687                 }
8688                 if (wanttangents && !svector3f)
8689                 {
8690                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8691                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8692                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8693                 }
8694         }
8695 }
8696
8697 float RSurf_FogPoint(const float *v)
8698 {
8699         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8700         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8701         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8702         float FogHeightFade = r_refdef.fogheightfade;
8703         float fogfrac;
8704         unsigned int fogmasktableindex;
8705         if (r_refdef.fogplaneviewabove)
8706                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8707         else
8708                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8709         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8710         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8711 }
8712
8713 float RSurf_FogVertex(const float *v)
8714 {
8715         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8716         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8717         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8718         float FogHeightFade = rsurface.fogheightfade;
8719         float fogfrac;
8720         unsigned int fogmasktableindex;
8721         if (r_refdef.fogplaneviewabove)
8722                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8723         else
8724                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8725         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8726         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8727 }
8728
8729 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8730 {
8731         int i;
8732         for (i = 0;i < numelements;i++)
8733                 outelement3i[i] = inelement3i[i] + adjust;
8734 }
8735
8736 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8737 extern cvar_t gl_vbo;
8738 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8739 {
8740         int deformindex;
8741         int firsttriangle;
8742         int numtriangles;
8743         int firstvertex;
8744         int endvertex;
8745         int numvertices;
8746         int surfacefirsttriangle;
8747         int surfacenumtriangles;
8748         int surfacefirstvertex;
8749         int surfaceendvertex;
8750         int surfacenumvertices;
8751         int batchnumvertices;
8752         int batchnumtriangles;
8753         int needsupdate;
8754         int i, j;
8755         qboolean gaps;
8756         qboolean dynamicvertex;
8757         float amplitude;
8758         float animpos;
8759         float scale;
8760         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8761         float waveparms[4];
8762         unsigned char *ub;
8763         q3shaderinfo_deform_t *deform;
8764         const msurface_t *surface, *firstsurface;
8765         r_vertexmesh_t *vertexmesh;
8766         if (!texturenumsurfaces)
8767                 return;
8768         // find vertex range of this surface batch
8769         gaps = false;
8770         firstsurface = texturesurfacelist[0];
8771         firsttriangle = firstsurface->num_firsttriangle;
8772         batchnumvertices = 0;
8773         batchnumtriangles = 0;
8774         firstvertex = endvertex = firstsurface->num_firstvertex;
8775         for (i = 0;i < texturenumsurfaces;i++)
8776         {
8777                 surface = texturesurfacelist[i];
8778                 if (surface != firstsurface + i)
8779                         gaps = true;
8780                 surfacefirstvertex = surface->num_firstvertex;
8781                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8782                 surfacenumvertices = surface->num_vertices;
8783                 surfacenumtriangles = surface->num_triangles;
8784                 if (firstvertex > surfacefirstvertex)
8785                         firstvertex = surfacefirstvertex;
8786                 if (endvertex < surfaceendvertex)
8787                         endvertex = surfaceendvertex;
8788                 batchnumvertices += surfacenumvertices;
8789                 batchnumtriangles += surfacenumtriangles;
8790         }
8791
8792         // we now know the vertex range used, and if there are any gaps in it
8793         rsurface.batchfirstvertex = firstvertex;
8794         rsurface.batchnumvertices = endvertex - firstvertex;
8795         rsurface.batchfirsttriangle = firsttriangle;
8796         rsurface.batchnumtriangles = batchnumtriangles;
8797
8798         // this variable holds flags for which properties have been updated that
8799         // may require regenerating vertexmesh array...
8800         needsupdate = 0;
8801
8802         // check if any dynamic vertex processing must occur
8803         dynamicvertex = false;
8804
8805         // a cvar to force the dynamic vertex path to be taken, for debugging
8806         if (r_batch_debugdynamicvertexpath.integer)
8807                 dynamicvertex = true;
8808
8809         // if there is a chance of animated vertex colors, it's a dynamic batch
8810         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8811         {
8812                 dynamicvertex = true;
8813                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8814         }
8815
8816         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8817         {
8818                 switch (deform->deform)
8819                 {
8820                 default:
8821                 case Q3DEFORM_PROJECTIONSHADOW:
8822                 case Q3DEFORM_TEXT0:
8823                 case Q3DEFORM_TEXT1:
8824                 case Q3DEFORM_TEXT2:
8825                 case Q3DEFORM_TEXT3:
8826                 case Q3DEFORM_TEXT4:
8827                 case Q3DEFORM_TEXT5:
8828                 case Q3DEFORM_TEXT6:
8829                 case Q3DEFORM_TEXT7:
8830                 case Q3DEFORM_NONE:
8831                         break;
8832                 case Q3DEFORM_AUTOSPRITE:
8833                         dynamicvertex = true;
8834                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8835                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8836                         break;
8837                 case Q3DEFORM_AUTOSPRITE2:
8838                         dynamicvertex = true;
8839                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8840                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8841                         break;
8842                 case Q3DEFORM_NORMAL:
8843                         dynamicvertex = true;
8844                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8845                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8846                         break;
8847                 case Q3DEFORM_WAVE:
8848                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8849                                 break; // if wavefunc is a nop, ignore this transform
8850                         dynamicvertex = true;
8851                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8852                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8853                         break;
8854                 case Q3DEFORM_BULGE:
8855                         dynamicvertex = true;
8856                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8857                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8858                         break;
8859                 case Q3DEFORM_MOVE:
8860                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8861                                 break; // if wavefunc is a nop, ignore this transform
8862                         dynamicvertex = true;
8863                         batchneed |= BATCHNEED_ARRAY_VERTEX;
8864                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8865                         break;
8866                 }
8867         }
8868         switch(rsurface.texture->tcgen.tcgen)
8869         {
8870         default:
8871         case Q3TCGEN_TEXTURE:
8872                 break;
8873         case Q3TCGEN_LIGHTMAP:
8874                 dynamicvertex = true;
8875                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8876                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8877                 break;
8878         case Q3TCGEN_VECTOR:
8879                 dynamicvertex = true;
8880                 batchneed |= BATCHNEED_ARRAY_VERTEX;
8881                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8882                 break;
8883         case Q3TCGEN_ENVIRONMENT:
8884                 dynamicvertex = true;
8885                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
8886                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8887                 break;
8888         }
8889         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8890         {
8891                 dynamicvertex = true;
8892                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8893                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8894         }
8895
8896         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8897         {
8898                 dynamicvertex = true;
8899                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8900         }
8901
8902         // when the model data has no vertex buffer (dynamic mesh), we need to
8903         // eliminate gaps
8904         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8905                 batchneed |= BATCHNEED_NOGAPS;
8906
8907         // the caller can specify BATCHNEED_NOGAPS to force a batch with
8908         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
8909         // we ensure this by treating the vertex batch as dynamic...
8910         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
8911                 dynamicvertex = true;
8912
8913         if (dynamicvertex)
8914         {
8915                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8916                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8917                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8918                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8919                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8920                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8921                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8922                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
8923         }
8924
8925         // if needsupdate, we have to do a dynamic vertex batch for sure
8926         if (needsupdate & batchneed)
8927                 dynamicvertex = true;
8928
8929         // see if we need to build vertexmesh from arrays
8930         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8931                 dynamicvertex = true;
8932
8933         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
8934         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
8935                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
8936
8937         rsurface.batchvertex3f = rsurface.modelvertex3f;
8938         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8939         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8940         rsurface.batchsvector3f = rsurface.modelsvector3f;
8941         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8942         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8943         rsurface.batchtvector3f = rsurface.modeltvector3f;
8944         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8945         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8946         rsurface.batchnormal3f = rsurface.modelnormal3f;
8947         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8948         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8949         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8950         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8951         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8952         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8953         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8954         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8955         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8956         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8957         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8958         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
8959         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
8960         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
8961         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
8962         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
8963         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
8964         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8965         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8966         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8967         rsurface.batchelement3i = rsurface.modelelement3i;
8968         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8969         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8970         rsurface.batchelement3s = rsurface.modelelement3s;
8971         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8972         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8973         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
8974         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
8975
8976         // if any dynamic vertex processing has to occur in software, we copy the
8977         // entire surface list together before processing to rebase the vertices
8978         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8979         //
8980         // if any gaps exist and we do not have a static vertex buffer, we have to
8981         // copy the surface list together to avoid wasting upload bandwidth on the
8982         // vertices in the gaps.
8983         //
8984         // if gaps exist and we have a static vertex buffer, we can choose whether
8985         // to combine the index buffer ranges into one dynamic index buffer or
8986         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
8987         //
8988         // in many cases the batch is reduced to one draw call.
8989
8990         rsurface.batchmultidraw = false;
8991         rsurface.batchmultidrawnumsurfaces = 0;
8992         rsurface.batchmultidrawsurfacelist = NULL;
8993
8994         if (!dynamicvertex)
8995         {
8996                 // static vertex data, just set pointers...
8997                 rsurface.batchgeneratedvertex = false;
8998                 // if there are gaps, we want to build a combined index buffer,
8999                 // otherwise use the original static buffer with an appropriate offset
9000                 if (gaps)
9001                 {
9002                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9003                         {
9004                                 rsurface.batchmultidraw = true;
9005                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9006                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9007                                 return;
9008                         }
9009                         // build a new triangle elements array for this batch
9010                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9011                         rsurface.batchfirsttriangle = 0;
9012                         numtriangles = 0;
9013                         for (i = 0;i < texturenumsurfaces;i++)
9014                         {
9015                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9016                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9017                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9018                                 numtriangles += surfacenumtriangles;
9019                         }
9020                         rsurface.batchelement3i_indexbuffer = NULL;
9021                         rsurface.batchelement3i_bufferoffset = 0;
9022                         rsurface.batchelement3s = NULL;
9023                         rsurface.batchelement3s_indexbuffer = NULL;
9024                         rsurface.batchelement3s_bufferoffset = 0;
9025                         if (endvertex <= 65536)
9026                         {
9027                                 // make a 16bit (unsigned short) index array if possible
9028                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9029                                 for (i = 0;i < numtriangles*3;i++)
9030                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9031                         }
9032                 }
9033                 return;
9034         }
9035
9036         // something needs software processing, do it for real...
9037         // we only directly handle separate array data in this case and then
9038         // generate interleaved data if needed...
9039         rsurface.batchgeneratedvertex = true;
9040
9041         // now copy the vertex data into a combined array and make an index array
9042         // (this is what Quake3 does all the time)
9043         // we also apply any skeletal animation here that would have been done in
9044         // the vertex shader, because most of the dynamic vertex animation cases
9045         // need actual vertex positions and normals
9046         //if (dynamicvertex)
9047         {
9048                 rsurface.batchvertex3fbuffer = NULL;
9049                 rsurface.batchvertexmesh = NULL;
9050                 rsurface.batchvertexmeshbuffer = NULL;
9051                 rsurface.batchvertex3f = NULL;
9052                 rsurface.batchvertex3f_vertexbuffer = NULL;
9053                 rsurface.batchvertex3f_bufferoffset = 0;
9054                 rsurface.batchsvector3f = NULL;
9055                 rsurface.batchsvector3f_vertexbuffer = NULL;
9056                 rsurface.batchsvector3f_bufferoffset = 0;
9057                 rsurface.batchtvector3f = NULL;
9058                 rsurface.batchtvector3f_vertexbuffer = NULL;
9059                 rsurface.batchtvector3f_bufferoffset = 0;
9060                 rsurface.batchnormal3f = NULL;
9061                 rsurface.batchnormal3f_vertexbuffer = NULL;
9062                 rsurface.batchnormal3f_bufferoffset = 0;
9063                 rsurface.batchlightmapcolor4f = NULL;
9064                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9065                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9066                 rsurface.batchtexcoordtexture2f = NULL;
9067                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9068                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9069                 rsurface.batchtexcoordlightmap2f = NULL;
9070                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9071                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9072                 rsurface.batchskeletalindex4ub = NULL;
9073                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9074                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9075                 rsurface.batchskeletalweight4ub = NULL;
9076                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9077                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9078                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9079                 rsurface.batchelement3i_indexbuffer = NULL;
9080                 rsurface.batchelement3i_bufferoffset = 0;
9081                 rsurface.batchelement3s = NULL;
9082                 rsurface.batchelement3s_indexbuffer = NULL;
9083                 rsurface.batchelement3s_bufferoffset = 0;
9084                 // we'll only be setting up certain arrays as needed
9085                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9086                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9087                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9088                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9089                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9090                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9091                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9092                 {
9093                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9094                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9095                 }
9096                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9097                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9098                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9099                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9100                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9101                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9102                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9103                 {
9104                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9105                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9106                 }
9107                 numvertices = 0;
9108                 numtriangles = 0;
9109                 for (i = 0;i < texturenumsurfaces;i++)
9110                 {
9111                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9112                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9113                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9114                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9115                         // copy only the data requested
9116                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9117                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9118                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9119                         {
9120                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9121                                 {
9122                                         if (rsurface.batchvertex3f)
9123                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9124                                         else
9125                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9126                                 }
9127                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9128                                 {
9129                                         if (rsurface.modelnormal3f)
9130                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9131                                         else
9132                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9133                                 }
9134                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9135                                 {
9136                                         if (rsurface.modelsvector3f)
9137                                         {
9138                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9139                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9140                                         }
9141                                         else
9142                                         {
9143                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9144                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9145                                         }
9146                                 }
9147                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9148                                 {
9149                                         if (rsurface.modellightmapcolor4f)
9150                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9151                                         else
9152                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9153                                 }
9154                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9155                                 {
9156                                         if (rsurface.modeltexcoordtexture2f)
9157                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9158                                         else
9159                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9160                                 }
9161                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9162                                 {
9163                                         if (rsurface.modeltexcoordlightmap2f)
9164                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9165                                         else
9166                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9167                                 }
9168                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9169                                 {
9170                                         if (rsurface.modelskeletalindex4ub)
9171                                         {
9172                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9173                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9174                                         }
9175                                         else
9176                                         {
9177                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9178                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9179                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9180                                                 for (j = 0;j < surfacenumvertices;j++)
9181                                                         ub[j*4] = 255;
9182                                         }
9183                                 }
9184                         }
9185                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9186                         numvertices += surfacenumvertices;
9187                         numtriangles += surfacenumtriangles;
9188                 }
9189
9190                 // generate a 16bit index array as well if possible
9191                 // (in general, dynamic batches fit)
9192                 if (numvertices <= 65536)
9193                 {
9194                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9195                         for (i = 0;i < numtriangles*3;i++)
9196                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9197                 }
9198
9199                 // since we've copied everything, the batch now starts at 0
9200                 rsurface.batchfirstvertex = 0;
9201                 rsurface.batchnumvertices = batchnumvertices;
9202                 rsurface.batchfirsttriangle = 0;
9203                 rsurface.batchnumtriangles = batchnumtriangles;
9204         }
9205
9206         // apply skeletal animation that would have been done in the vertex shader
9207         if (rsurface.batchskeletaltransform3x4)
9208         {
9209                 const unsigned char *si;
9210                 const unsigned char *sw;
9211                 const float *t[4];
9212                 const float *b = rsurface.batchskeletaltransform3x4;
9213                 float *vp, *vs, *vt, *vn;
9214                 float w[4];
9215                 float m[3][4], n[3][4];
9216                 float tp[3], ts[3], tt[3], tn[3];
9217                 si = rsurface.batchskeletalindex4ub;
9218                 sw = rsurface.batchskeletalweight4ub;
9219                 vp = rsurface.batchvertex3f;
9220                 vs = rsurface.batchsvector3f;
9221                 vt = rsurface.batchtvector3f;
9222                 vn = rsurface.batchnormal3f;
9223                 memset(m[0], 0, sizeof(m));
9224                 memset(n[0], 0, sizeof(n));
9225                 for (i = 0;i < batchnumvertices;i++)
9226                 {
9227                         t[0] = b + si[0]*12;
9228                         if (sw[0] == 255)
9229                         {
9230                                 // common case - only one matrix
9231                                 m[0][0] = t[0][ 0];
9232                                 m[0][1] = t[0][ 1];
9233                                 m[0][2] = t[0][ 2];
9234                                 m[0][3] = t[0][ 3];
9235                                 m[1][0] = t[0][ 4];
9236                                 m[1][1] = t[0][ 5];
9237                                 m[1][2] = t[0][ 6];
9238                                 m[1][3] = t[0][ 7];
9239                                 m[2][0] = t[0][ 8];
9240                                 m[2][1] = t[0][ 9];
9241                                 m[2][2] = t[0][10];
9242                                 m[2][3] = t[0][11];
9243                         }
9244                         else if (sw[2] + sw[3])
9245                         {
9246                                 // blend 4 matrices
9247                                 t[1] = b + si[1]*12;
9248                                 t[2] = b + si[2]*12;
9249                                 t[3] = b + si[3]*12;
9250                                 w[0] = sw[0] * (1.0f / 255.0f);
9251                                 w[1] = sw[1] * (1.0f / 255.0f);
9252                                 w[2] = sw[2] * (1.0f / 255.0f);
9253                                 w[3] = sw[3] * (1.0f / 255.0f);
9254                                 // blend the matrices
9255                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9256                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9257                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9258                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9259                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9260                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9261                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9262                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9263                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9264                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9265                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9266                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9267                         }
9268                         else
9269                         {
9270                                 // blend 2 matrices
9271                                 t[1] = b + si[1]*12;
9272                                 w[0] = sw[0] * (1.0f / 255.0f);
9273                                 w[1] = sw[1] * (1.0f / 255.0f);
9274                                 // blend the matrices
9275                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9276                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9277                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9278                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9279                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9280                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9281                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9282                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9283                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9284                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9285                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9286                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9287                         }
9288                         si += 4;
9289                         sw += 4;
9290                         // modify the vertex
9291                         VectorCopy(vp, tp);
9292                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9293                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9294                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9295                         vp += 3;
9296                         if (vn)
9297                         {
9298                                 // the normal transformation matrix is a set of cross products...
9299                                 CrossProduct(m[1], m[2], n[0]);
9300                                 CrossProduct(m[2], m[0], n[1]);
9301                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9302                                 VectorCopy(vn, tn);
9303                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9304                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9305                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9306                                 VectorNormalize(vn);
9307                                 vn += 3;
9308                                 if (vs)
9309                                 {
9310                                         VectorCopy(vs, ts);
9311                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9312                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9313                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9314                                         VectorNormalize(vs);
9315                                         vs += 3;
9316                                         VectorCopy(vt, tt);
9317                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9318                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9319                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9320                                         VectorNormalize(vt);
9321                                         vt += 3;
9322                                 }
9323                         }
9324                 }
9325                 rsurface.batchskeletaltransform3x4 = NULL;
9326                 rsurface.batchskeletalnumtransforms = 0;
9327         }
9328
9329         // q1bsp surfaces rendered in vertex color mode have to have colors
9330         // calculated based on lightstyles
9331         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9332         {
9333                 // generate color arrays for the surfaces in this list
9334                 int c[4];
9335                 int scale;
9336                 int size3;
9337                 const int *offsets;
9338                 const unsigned char *lm;
9339                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9340                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9341                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9342                 numvertices = 0;
9343                 for (i = 0;i < texturenumsurfaces;i++)
9344                 {
9345                         surface = texturesurfacelist[i];
9346                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9347                         surfacenumvertices = surface->num_vertices;
9348                         if (surface->lightmapinfo->samples)
9349                         {
9350                                 for (j = 0;j < surfacenumvertices;j++)
9351                                 {
9352                                         lm = surface->lightmapinfo->samples + offsets[j];
9353                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9354                                         VectorScale(lm, scale, c);
9355                                         if (surface->lightmapinfo->styles[1] != 255)
9356                                         {
9357                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9358                                                 lm += size3;
9359                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9360                                                 VectorMA(c, scale, lm, c);
9361                                                 if (surface->lightmapinfo->styles[2] != 255)
9362                                                 {
9363                                                         lm += size3;
9364                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9365                                                         VectorMA(c, scale, lm, c);
9366                                                         if (surface->lightmapinfo->styles[3] != 255)
9367                                                         {
9368                                                                 lm += size3;
9369                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9370                                                                 VectorMA(c, scale, lm, c);
9371                                                         }
9372                                                 }
9373                                         }
9374                                         c[0] >>= 7;
9375                                         c[1] >>= 7;
9376                                         c[2] >>= 7;
9377                                         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);
9378                                         numvertices++;
9379                                 }
9380                         }
9381                         else
9382                         {
9383                                 for (j = 0;j < surfacenumvertices;j++)
9384                                 {
9385                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9386                                         numvertices++;
9387                                 }
9388                         }
9389                 }
9390         }
9391
9392         // if vertices are deformed (sprite flares and things in maps, possibly
9393         // water waves, bulges and other deformations), modify the copied vertices
9394         // in place
9395         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9396         {
9397                 switch (deform->deform)
9398                 {
9399                 default:
9400                 case Q3DEFORM_PROJECTIONSHADOW:
9401                 case Q3DEFORM_TEXT0:
9402                 case Q3DEFORM_TEXT1:
9403                 case Q3DEFORM_TEXT2:
9404                 case Q3DEFORM_TEXT3:
9405                 case Q3DEFORM_TEXT4:
9406                 case Q3DEFORM_TEXT5:
9407                 case Q3DEFORM_TEXT6:
9408                 case Q3DEFORM_TEXT7:
9409                 case Q3DEFORM_NONE:
9410                         break;
9411                 case Q3DEFORM_AUTOSPRITE:
9412                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9413                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9414                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9415                         VectorNormalize(newforward);
9416                         VectorNormalize(newright);
9417                         VectorNormalize(newup);
9418 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9419 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9420 //                      rsurface.batchvertex3f_bufferoffset = 0;
9421 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9422 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9423 //                      rsurface.batchsvector3f_bufferoffset = 0;
9424 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9425 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9426 //                      rsurface.batchtvector3f_bufferoffset = 0;
9427 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9428 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9429 //                      rsurface.batchnormal3f_bufferoffset = 0;
9430                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9431                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9432                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9433                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9434                                 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);
9435                         // a single autosprite surface can contain multiple sprites...
9436                         for (j = 0;j < batchnumvertices - 3;j += 4)
9437                         {
9438                                 VectorClear(center);
9439                                 for (i = 0;i < 4;i++)
9440                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9441                                 VectorScale(center, 0.25f, center);
9442                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9443                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9444                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9445                                 for (i = 0;i < 4;i++)
9446                                 {
9447                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9448                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9449                                 }
9450                         }
9451                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9452                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9453                         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);
9454                         break;
9455                 case Q3DEFORM_AUTOSPRITE2:
9456                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9457                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9458                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9459                         VectorNormalize(newforward);
9460                         VectorNormalize(newright);
9461                         VectorNormalize(newup);
9462 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9463 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9464 //                      rsurface.batchvertex3f_bufferoffset = 0;
9465                         {
9466                                 const float *v1, *v2;
9467                                 vec3_t start, end;
9468                                 float f, l;
9469                                 struct
9470                                 {
9471                                         float length2;
9472                                         const float *v1;
9473                                         const float *v2;
9474                                 }
9475                                 shortest[2];
9476                                 memset(shortest, 0, sizeof(shortest));
9477                                 // a single autosprite surface can contain multiple sprites...
9478                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9479                                 {
9480                                         VectorClear(center);
9481                                         for (i = 0;i < 4;i++)
9482                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9483                                         VectorScale(center, 0.25f, center);
9484                                         // find the two shortest edges, then use them to define the
9485                                         // axis vectors for rotating around the central axis
9486                                         for (i = 0;i < 6;i++)
9487                                         {
9488                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9489                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9490                                                 l = VectorDistance2(v1, v2);
9491                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9492                                                 if (v1[2] != v2[2])
9493                                                         l += (1.0f / 1024.0f);
9494                                                 if (shortest[0].length2 > l || i == 0)
9495                                                 {
9496                                                         shortest[1] = shortest[0];
9497                                                         shortest[0].length2 = l;
9498                                                         shortest[0].v1 = v1;
9499                                                         shortest[0].v2 = v2;
9500                                                 }
9501                                                 else if (shortest[1].length2 > l || i == 1)
9502                                                 {
9503                                                         shortest[1].length2 = l;
9504                                                         shortest[1].v1 = v1;
9505                                                         shortest[1].v2 = v2;
9506                                                 }
9507                                         }
9508                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9509                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9510                                         // this calculates the right vector from the shortest edge
9511                                         // and the up vector from the edge midpoints
9512                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9513                                         VectorNormalize(right);
9514                                         VectorSubtract(end, start, up);
9515                                         VectorNormalize(up);
9516                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9517                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9518                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9519                                         VectorNegate(forward, forward);
9520                                         VectorReflect(forward, 0, up, forward);
9521                                         VectorNormalize(forward);
9522                                         CrossProduct(up, forward, newright);
9523                                         VectorNormalize(newright);
9524                                         // rotate the quad around the up axis vector, this is made
9525                                         // especially easy by the fact we know the quad is flat,
9526                                         // so we only have to subtract the center position and
9527                                         // measure distance along the right vector, and then
9528                                         // multiply that by the newright vector and add back the
9529                                         // center position
9530                                         // we also need to subtract the old position to undo the
9531                                         // displacement from the center, which we do with a
9532                                         // DotProduct, the subtraction/addition of center is also
9533                                         // optimized into DotProducts here
9534                                         l = DotProduct(right, center);
9535                                         for (i = 0;i < 4;i++)
9536                                         {
9537                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9538                                                 f = DotProduct(right, v1) - l;
9539                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9540                                         }
9541                                 }
9542                         }
9543                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9544                         {
9545 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9546 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9547 //                              rsurface.batchnormal3f_bufferoffset = 0;
9548                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9549                         }
9550                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9551                         {
9552 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9553 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9554 //                              rsurface.batchsvector3f_bufferoffset = 0;
9555 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9556 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9557 //                              rsurface.batchtvector3f_bufferoffset = 0;
9558                                 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);
9559                         }
9560                         break;
9561                 case Q3DEFORM_NORMAL:
9562                         // deform the normals to make reflections wavey
9563                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9564                         rsurface.batchnormal3f_vertexbuffer = NULL;
9565                         rsurface.batchnormal3f_bufferoffset = 0;
9566                         for (j = 0;j < batchnumvertices;j++)
9567                         {
9568                                 float vertex[3];
9569                                 float *normal = rsurface.batchnormal3f + 3*j;
9570                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9571                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9572                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9573                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9574                                 VectorNormalize(normal);
9575                         }
9576                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9577                         {
9578 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9579 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9580 //                              rsurface.batchsvector3f_bufferoffset = 0;
9581 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9582 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9583 //                              rsurface.batchtvector3f_bufferoffset = 0;
9584                                 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);
9585                         }
9586                         break;
9587                 case Q3DEFORM_WAVE:
9588                         // deform vertex array to make wavey water and flags and such
9589                         waveparms[0] = deform->waveparms[0];
9590                         waveparms[1] = deform->waveparms[1];
9591                         waveparms[2] = deform->waveparms[2];
9592                         waveparms[3] = deform->waveparms[3];
9593                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9594                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9595                         // this is how a divisor of vertex influence on deformation
9596                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9597                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9598 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9599 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9600 //                      rsurface.batchvertex3f_bufferoffset = 0;
9601 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9602 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9603 //                      rsurface.batchnormal3f_bufferoffset = 0;
9604                         for (j = 0;j < batchnumvertices;j++)
9605                         {
9606                                 // if the wavefunc depends on time, evaluate it per-vertex
9607                                 if (waveparms[3])
9608                                 {
9609                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9610                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9611                                 }
9612                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9613                         }
9614                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9615                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9616                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9617                         {
9618 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9619 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9620 //                              rsurface.batchsvector3f_bufferoffset = 0;
9621 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9622 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9623 //                              rsurface.batchtvector3f_bufferoffset = 0;
9624                                 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);
9625                         }
9626                         break;
9627                 case Q3DEFORM_BULGE:
9628                         // deform vertex array to make the surface have moving bulges
9629 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9630 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9631 //                      rsurface.batchvertex3f_bufferoffset = 0;
9632 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9633 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9634 //                      rsurface.batchnormal3f_bufferoffset = 0;
9635                         for (j = 0;j < batchnumvertices;j++)
9636                         {
9637                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9638                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9639                         }
9640                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9641                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9642                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9643                         {
9644 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9645 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9646 //                              rsurface.batchsvector3f_bufferoffset = 0;
9647 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9648 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9649 //                              rsurface.batchtvector3f_bufferoffset = 0;
9650                                 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);
9651                         }
9652                         break;
9653                 case Q3DEFORM_MOVE:
9654                         // deform vertex array
9655                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9656                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9657                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9658                         VectorScale(deform->parms, scale, waveparms);
9659 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9660 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9661 //                      rsurface.batchvertex3f_bufferoffset = 0;
9662                         for (j = 0;j < batchnumvertices;j++)
9663                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9664                         break;
9665                 }
9666         }
9667
9668         // generate texcoords based on the chosen texcoord source
9669         switch(rsurface.texture->tcgen.tcgen)
9670         {
9671         default:
9672         case Q3TCGEN_TEXTURE:
9673                 break;
9674         case Q3TCGEN_LIGHTMAP:
9675 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9676 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9677 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9678                 if (rsurface.batchtexcoordlightmap2f)
9679                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9680                 break;
9681         case Q3TCGEN_VECTOR:
9682 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9683 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9684 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9685                 for (j = 0;j < batchnumvertices;j++)
9686                 {
9687                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9688                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9689                 }
9690                 break;
9691         case Q3TCGEN_ENVIRONMENT:
9692                 // make environment reflections using a spheremap
9693                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9694                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9695                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9696                 for (j = 0;j < batchnumvertices;j++)
9697                 {
9698                         // identical to Q3A's method, but executed in worldspace so
9699                         // carried models can be shiny too
9700
9701                         float viewer[3], d, reflected[3], worldreflected[3];
9702
9703                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9704                         // VectorNormalize(viewer);
9705
9706                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9707
9708                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9709                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9710                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9711                         // note: this is proportinal to viewer, so we can normalize later
9712
9713                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9714                         VectorNormalize(worldreflected);
9715
9716                         // note: this sphere map only uses world x and z!
9717                         // so positive and negative y will LOOK THE SAME.
9718                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9719                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9720                 }
9721                 break;
9722         }
9723         // the only tcmod that needs software vertex processing is turbulent, so
9724         // check for it here and apply the changes if needed
9725         // and we only support that as the first one
9726         // (handling a mixture of turbulent and other tcmods would be problematic
9727         //  without punting it entirely to a software path)
9728         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9729         {
9730                 amplitude = rsurface.texture->tcmods[0].parms[1];
9731                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9732 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9733 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9734 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9735                 for (j = 0;j < batchnumvertices;j++)
9736                 {
9737                         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);
9738                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9739                 }
9740         }
9741
9742         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9743         {
9744                 // convert the modified arrays to vertex structs
9745 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9746 //              rsurface.batchvertexmeshbuffer = NULL;
9747                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9748                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9749                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9750                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9751                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9752                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9753                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9754                 {
9755                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9756                         {
9757                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9758                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9759                         }
9760                 }
9761                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9762                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9763                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9764                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9765                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9766                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9767                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9768                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9769                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9770                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9771                 {
9772                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9773                         {
9774                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9775                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9776                         }
9777                 }
9778         }
9779 }
9780
9781 void RSurf_DrawBatch(void)
9782 {
9783         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9784         // through the pipeline, killing it earlier in the pipeline would have
9785         // per-surface overhead rather than per-batch overhead, so it's best to
9786         // reject it here, before it hits glDraw.
9787         if (rsurface.batchnumtriangles == 0)
9788                 return;
9789 #if 0
9790         // batch debugging code
9791         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9792         {
9793                 int i;
9794                 int j;
9795                 int c;
9796                 const int *e;
9797                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9798                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9799                 {
9800                         c = e[i];
9801                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9802                         {
9803                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9804                                 {
9805                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9806                                                 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);
9807                                         break;
9808                                 }
9809                         }
9810                 }
9811         }
9812 #endif
9813         if (rsurface.batchmultidraw)
9814         {
9815                 // issue multiple draws rather than copying index data
9816                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
9817                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
9818                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
9819                 for (i = 0;i < numsurfaces;)
9820                 {
9821                         // combine consecutive surfaces as one draw
9822                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
9823                                 if (surfacelist[j] != surfacelist[k] + 1)
9824                                         break;
9825                         firstvertex = surfacelist[i]->num_firstvertex;
9826                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
9827                         firsttriangle = surfacelist[i]->num_firsttriangle;
9828                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
9829                         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);
9830                         i = j;
9831                 }
9832         }
9833         else
9834         {
9835                 // there is only one consecutive run of index data (may have been combined)
9836                 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);
9837         }
9838 }
9839
9840 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9841 {
9842         // pick the closest matching water plane
9843         int planeindex, vertexindex, bestplaneindex = -1;
9844         float d, bestd;
9845         vec3_t vert;
9846         const float *v;
9847         r_waterstate_waterplane_t *p;
9848         qboolean prepared = false;
9849         bestd = 0;
9850         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9851         {
9852                 if(p->camera_entity != rsurface.texture->camera_entity)
9853                         continue;
9854                 d = 0;
9855                 if(!prepared)
9856                 {
9857                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
9858                         prepared = true;
9859                         if(rsurface.batchnumvertices == 0)
9860                                 break;
9861                 }
9862                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9863                 {
9864                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9865                         d += fabs(PlaneDiff(vert, &p->plane));
9866                 }
9867                 if (bestd > d || bestplaneindex < 0)
9868                 {
9869                         bestd = d;
9870                         bestplaneindex = planeindex;
9871                 }
9872         }
9873         return bestplaneindex;
9874         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9875         // this situation though, as it might be better to render single larger
9876         // batches with useless stuff (backface culled for example) than to
9877         // render multiple smaller batches
9878 }
9879
9880 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9881 {
9882         int i;
9883         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9884         rsurface.passcolor4f_vertexbuffer = 0;
9885         rsurface.passcolor4f_bufferoffset = 0;
9886         for (i = 0;i < rsurface.batchnumvertices;i++)
9887                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9888 }
9889
9890 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9891 {
9892         int i;
9893         float f;
9894         const float *v;
9895         const float *c;
9896         float *c2;
9897         if (rsurface.passcolor4f)
9898         {
9899                 // generate color arrays
9900                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9901                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9902                 rsurface.passcolor4f_vertexbuffer = 0;
9903                 rsurface.passcolor4f_bufferoffset = 0;
9904                 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)
9905                 {
9906                         f = RSurf_FogVertex(v);
9907                         c2[0] = c[0] * f;
9908                         c2[1] = c[1] * f;
9909                         c2[2] = c[2] * f;
9910                         c2[3] = c[3];
9911                 }
9912         }
9913         else
9914         {
9915                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9916                 rsurface.passcolor4f_vertexbuffer = 0;
9917                 rsurface.passcolor4f_bufferoffset = 0;
9918                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9919                 {
9920                         f = RSurf_FogVertex(v);
9921                         c2[0] = f;
9922                         c2[1] = f;
9923                         c2[2] = f;
9924                         c2[3] = 1;
9925                 }
9926         }
9927 }
9928
9929 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9930 {
9931         int i;
9932         float f;
9933         const float *v;
9934         const float *c;
9935         float *c2;
9936         if (!rsurface.passcolor4f)
9937                 return;
9938         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9939         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9940         rsurface.passcolor4f_vertexbuffer = 0;
9941         rsurface.passcolor4f_bufferoffset = 0;
9942         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)
9943         {
9944                 f = RSurf_FogVertex(v);
9945                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9946                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9947                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9948                 c2[3] = c[3];
9949         }
9950 }
9951
9952 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9953 {
9954         int i;
9955         const float *c;
9956         float *c2;
9957         if (!rsurface.passcolor4f)
9958                 return;
9959         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9960         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9961         rsurface.passcolor4f_vertexbuffer = 0;
9962         rsurface.passcolor4f_bufferoffset = 0;
9963         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9964         {
9965                 c2[0] = c[0] * r;
9966                 c2[1] = c[1] * g;
9967                 c2[2] = c[2] * b;
9968                 c2[3] = c[3] * a;
9969         }
9970 }
9971
9972 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9973 {
9974         int i;
9975         const float *c;
9976         float *c2;
9977         if (!rsurface.passcolor4f)
9978                 return;
9979         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9980         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9981         rsurface.passcolor4f_vertexbuffer = 0;
9982         rsurface.passcolor4f_bufferoffset = 0;
9983         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9984         {
9985                 c2[0] = c[0] + r_refdef.scene.ambient;
9986                 c2[1] = c[1] + r_refdef.scene.ambient;
9987                 c2[2] = c[2] + r_refdef.scene.ambient;
9988                 c2[3] = c[3];
9989         }
9990 }
9991
9992 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9993 {
9994         // TODO: optimize
9995         rsurface.passcolor4f = NULL;
9996         rsurface.passcolor4f_vertexbuffer = 0;
9997         rsurface.passcolor4f_bufferoffset = 0;
9998         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9999         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10000         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10001         GL_Color(r, g, b, a);
10002         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10003         RSurf_DrawBatch();
10004 }
10005
10006 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10007 {
10008         // TODO: optimize applyfog && applycolor case
10009         // just apply fog if necessary, and tint the fog color array if necessary
10010         rsurface.passcolor4f = NULL;
10011         rsurface.passcolor4f_vertexbuffer = 0;
10012         rsurface.passcolor4f_bufferoffset = 0;
10013         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10014         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10015         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10016         GL_Color(r, g, b, a);
10017         RSurf_DrawBatch();
10018 }
10019
10020 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10021 {
10022         // TODO: optimize
10023         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10024         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10025         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10026         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10027         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10028         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10029         GL_Color(r, g, b, a);
10030         RSurf_DrawBatch();
10031 }
10032
10033 static void RSurf_DrawBatch_GL11_ClampColor(void)
10034 {
10035         int i;
10036         const float *c1;
10037         float *c2;
10038         if (!rsurface.passcolor4f)
10039                 return;
10040         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10041         {
10042                 c2[0] = bound(0.0f, c1[0], 1.0f);
10043                 c2[1] = bound(0.0f, c1[1], 1.0f);
10044                 c2[2] = bound(0.0f, c1[2], 1.0f);
10045                 c2[3] = bound(0.0f, c1[3], 1.0f);
10046         }
10047 }
10048
10049 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10050 {
10051         int i;
10052         float f;
10053         const float *v;
10054         const float *n;
10055         float *c;
10056         //vec3_t eyedir;
10057
10058         // fake shading
10059         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10060         rsurface.passcolor4f_vertexbuffer = 0;
10061         rsurface.passcolor4f_bufferoffset = 0;
10062         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)
10063         {
10064                 f = -DotProduct(r_refdef.view.forward, n);
10065                 f = max(0, f);
10066                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10067                 f *= r_refdef.lightmapintensity;
10068                 Vector4Set(c, f, f, f, 1);
10069         }
10070 }
10071
10072 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10073 {
10074         RSurf_DrawBatch_GL11_ApplyFakeLight();
10075         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10076         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10077         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10078         GL_Color(r, g, b, a);
10079         RSurf_DrawBatch();
10080 }
10081
10082 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10083 {
10084         int i;
10085         float f;
10086         float alpha;
10087         const float *v;
10088         const float *n;
10089         float *c;
10090         vec3_t ambientcolor;
10091         vec3_t diffusecolor;
10092         vec3_t lightdir;
10093         // TODO: optimize
10094         // model lighting
10095         VectorCopy(rsurface.modellight_lightdir, lightdir);
10096         f = 0.5f * r_refdef.lightmapintensity;
10097         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10098         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10099         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10100         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10101         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10102         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10103         alpha = *a;
10104         if (VectorLength2(diffusecolor) > 0)
10105         {
10106                 // q3-style directional shading
10107                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10108                 rsurface.passcolor4f_vertexbuffer = 0;
10109                 rsurface.passcolor4f_bufferoffset = 0;
10110                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
10111                 {
10112                         if ((f = DotProduct(n, lightdir)) > 0)
10113                                 VectorMA(ambientcolor, f, diffusecolor, c);
10114                         else
10115                                 VectorCopy(ambientcolor, c);
10116                         c[3] = alpha;
10117                 }
10118                 *r = 1;
10119                 *g = 1;
10120                 *b = 1;
10121                 *a = 1;
10122                 *applycolor = false;
10123         }
10124         else
10125         {
10126                 *r = ambientcolor[0];
10127                 *g = ambientcolor[1];
10128                 *b = ambientcolor[2];
10129                 rsurface.passcolor4f = NULL;
10130                 rsurface.passcolor4f_vertexbuffer = 0;
10131                 rsurface.passcolor4f_bufferoffset = 0;
10132         }
10133 }
10134
10135 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10136 {
10137         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10138         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10139         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10140         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10141         GL_Color(r, g, b, a);
10142         RSurf_DrawBatch();
10143 }
10144
10145 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10146 {
10147         int i;
10148         float f;
10149         const float *v;
10150         float *c;
10151
10152         // fake shading
10153         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10154         rsurface.passcolor4f_vertexbuffer = 0;
10155         rsurface.passcolor4f_bufferoffset = 0;
10156
10157         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10158         {
10159                 f = 1 - RSurf_FogVertex(v);
10160                 c[0] = r;
10161                 c[1] = g;
10162                 c[2] = b;
10163                 c[3] = f * a;
10164         }
10165 }
10166
10167 void RSurf_SetupDepthAndCulling(void)
10168 {
10169         // submodels are biased to avoid z-fighting with world surfaces that they
10170         // may be exactly overlapping (avoids z-fighting artifacts on certain
10171         // doors and things in Quake maps)
10172         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10173         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10174         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10175         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10176 }
10177
10178 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10179 {
10180         // transparent sky would be ridiculous
10181         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10182                 return;
10183         R_SetupShader_Generic_NoTexture(false, false);
10184         skyrenderlater = true;
10185         RSurf_SetupDepthAndCulling();
10186         GL_DepthMask(true);
10187         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10188         // skymasking on them, and Quake3 never did sky masking (unlike
10189         // software Quake and software Quake2), so disable the sky masking
10190         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10191         // and skymasking also looks very bad when noclipping outside the
10192         // level, so don't use it then either.
10193         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10194         {
10195                 R_Mesh_ResetTextureState();
10196                 if (skyrendermasked)
10197                 {
10198                         R_SetupShader_DepthOrShadow(false, false, false);
10199                         // depth-only (masking)
10200                         GL_ColorMask(0,0,0,0);
10201                         // just to make sure that braindead drivers don't draw
10202                         // anything despite that colormask...
10203                         GL_BlendFunc(GL_ZERO, GL_ONE);
10204                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10205                         if (rsurface.batchvertex3fbuffer)
10206                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10207                         else
10208                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10209                 }
10210                 else
10211                 {
10212                         R_SetupShader_Generic_NoTexture(false, false);
10213                         // fog sky
10214                         GL_BlendFunc(GL_ONE, GL_ZERO);
10215                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10216                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10217                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10218                 }
10219                 RSurf_DrawBatch();
10220                 if (skyrendermasked)
10221                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10222         }
10223         R_Mesh_ResetTextureState();
10224         GL_Color(1, 1, 1, 1);
10225 }
10226
10227 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10228 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10229 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10230 {
10231         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10232                 return;
10233         if (prepass)
10234         {
10235                 // render screenspace normalmap to texture
10236                 GL_DepthMask(true);
10237                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10238                 RSurf_DrawBatch();
10239                 return;
10240         }
10241
10242         // bind lightmap texture
10243
10244         // water/refraction/reflection/camera surfaces have to be handled specially
10245         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10246         {
10247                 int start, end, startplaneindex;
10248                 for (start = 0;start < texturenumsurfaces;start = end)
10249                 {
10250                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10251                         if(startplaneindex < 0)
10252                         {
10253                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10254                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10255                                 end = start + 1;
10256                                 continue;
10257                         }
10258                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10259                                 ;
10260                         // now that we have a batch using the same planeindex, render it
10261                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10262                         {
10263                                 // render water or distortion background
10264                                 GL_DepthMask(true);
10265                                 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);
10266                                 RSurf_DrawBatch();
10267                                 // blend surface on top
10268                                 GL_DepthMask(false);
10269                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10270                                 RSurf_DrawBatch();
10271                         }
10272                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10273                         {
10274                                 // render surface with reflection texture as input
10275                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10276                                 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);
10277                                 RSurf_DrawBatch();
10278                         }
10279                 }
10280                 return;
10281         }
10282
10283         // render surface batch normally
10284         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10285         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);
10286         RSurf_DrawBatch();
10287 }
10288
10289 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10290 {
10291         // OpenGL 1.3 path - anything not completely ancient
10292         qboolean applycolor;
10293         qboolean applyfog;
10294         int layerindex;
10295         const texturelayer_t *layer;
10296         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);
10297         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10298
10299         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10300         {
10301                 vec4_t layercolor;
10302                 int layertexrgbscale;
10303                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10304                 {
10305                         if (layerindex == 0)
10306                                 GL_AlphaTest(true);
10307                         else
10308                         {
10309                                 GL_AlphaTest(false);
10310                                 GL_DepthFunc(GL_EQUAL);
10311                         }
10312                 }
10313                 GL_DepthMask(layer->depthmask && writedepth);
10314                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10315                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10316                 {
10317                         layertexrgbscale = 4;
10318                         VectorScale(layer->color, 0.25f, layercolor);
10319                 }
10320                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10321                 {
10322                         layertexrgbscale = 2;
10323                         VectorScale(layer->color, 0.5f, layercolor);
10324                 }
10325                 else
10326                 {
10327                         layertexrgbscale = 1;
10328                         VectorScale(layer->color, 1.0f, layercolor);
10329                 }
10330                 layercolor[3] = layer->color[3];
10331                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10332                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10333                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10334                 switch (layer->type)
10335                 {
10336                 case TEXTURELAYERTYPE_LITTEXTURE:
10337                         // single-pass lightmapped texture with 2x rgbscale
10338                         R_Mesh_TexBind(0, r_texture_white);
10339                         R_Mesh_TexMatrix(0, NULL);
10340                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10341                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10342                         R_Mesh_TexBind(1, layer->texture);
10343                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10344                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10345                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10346                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10347                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10348                         else if (FAKELIGHT_ENABLED)
10349                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10350                         else if (rsurface.uselightmaptexture)
10351                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10352                         else
10353                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10354                         break;
10355                 case TEXTURELAYERTYPE_TEXTURE:
10356                         // singletexture unlit texture with transparency support
10357                         R_Mesh_TexBind(0, layer->texture);
10358                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10359                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10360                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10361                         R_Mesh_TexBind(1, 0);
10362                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10363                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10364                         break;
10365                 case TEXTURELAYERTYPE_FOG:
10366                         // singletexture fogging
10367                         if (layer->texture)
10368                         {
10369                                 R_Mesh_TexBind(0, layer->texture);
10370                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10371                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10372                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10373                         }
10374                         else
10375                         {
10376                                 R_Mesh_TexBind(0, 0);
10377                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10378                         }
10379                         R_Mesh_TexBind(1, 0);
10380                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10381                         // generate a color array for the fog pass
10382                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10383                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10384                         RSurf_DrawBatch();
10385                         break;
10386                 default:
10387                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10388                 }
10389         }
10390         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10391         {
10392                 GL_DepthFunc(GL_LEQUAL);
10393                 GL_AlphaTest(false);
10394         }
10395 }
10396
10397 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10398 {
10399         // OpenGL 1.1 - crusty old voodoo path
10400         qboolean applyfog;
10401         int layerindex;
10402         const texturelayer_t *layer;
10403         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);
10404         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10405
10406         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10407         {
10408                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10409                 {
10410                         if (layerindex == 0)
10411                                 GL_AlphaTest(true);
10412                         else
10413                         {
10414                                 GL_AlphaTest(false);
10415                                 GL_DepthFunc(GL_EQUAL);
10416                         }
10417                 }
10418                 GL_DepthMask(layer->depthmask && writedepth);
10419                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10420                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10421                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10422                 switch (layer->type)
10423                 {
10424                 case TEXTURELAYERTYPE_LITTEXTURE:
10425                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10426                         {
10427                                 // two-pass lit texture with 2x rgbscale
10428                                 // first the lightmap pass
10429                                 R_Mesh_TexBind(0, r_texture_white);
10430                                 R_Mesh_TexMatrix(0, NULL);
10431                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10432                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10433                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10434                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10435                                 else if (FAKELIGHT_ENABLED)
10436                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10437                                 else if (rsurface.uselightmaptexture)
10438                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10439                                 else
10440                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10441                                 // then apply the texture to it
10442                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10443                                 R_Mesh_TexBind(0, layer->texture);
10444                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10445                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10446                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10447                                 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);
10448                         }
10449                         else
10450                         {
10451                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10452                                 R_Mesh_TexBind(0, layer->texture);
10453                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10454                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10455                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10456                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10457                                         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);
10458                                 else if (FAKELIGHT_ENABLED)
10459                                         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);
10460                                 else
10461                                         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);
10462                         }
10463                         break;
10464                 case TEXTURELAYERTYPE_TEXTURE:
10465                         // singletexture unlit texture with transparency support
10466                         R_Mesh_TexBind(0, layer->texture);
10467                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10468                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10469                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10470                         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);
10471                         break;
10472                 case TEXTURELAYERTYPE_FOG:
10473                         // singletexture fogging
10474                         if (layer->texture)
10475                         {
10476                                 R_Mesh_TexBind(0, layer->texture);
10477                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10478                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10479                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10480                         }
10481                         else
10482                         {
10483                                 R_Mesh_TexBind(0, 0);
10484                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10485                         }
10486                         // generate a color array for the fog pass
10487                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10488                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10489                         RSurf_DrawBatch();
10490                         break;
10491                 default:
10492                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10493                 }
10494         }
10495         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10496         {
10497                 GL_DepthFunc(GL_LEQUAL);
10498                 GL_AlphaTest(false);
10499         }
10500 }
10501
10502 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10503 {
10504         int vi;
10505         int j;
10506         r_vertexgeneric_t *batchvertex;
10507         float c[4];
10508
10509 //      R_Mesh_ResetTextureState();
10510         R_SetupShader_Generic_NoTexture(false, false);
10511
10512         if(rsurface.texture && rsurface.texture->currentskinframe)
10513         {
10514                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10515                 c[3] *= rsurface.texture->currentalpha;
10516         }
10517         else
10518         {
10519                 c[0] = 1;
10520                 c[1] = 0;
10521                 c[2] = 1;
10522                 c[3] = 1;
10523         }
10524
10525         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10526         {
10527                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10528                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10529                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10530         }
10531
10532         // brighten it up (as texture value 127 means "unlit")
10533         c[0] *= 2 * r_refdef.view.colorscale;
10534         c[1] *= 2 * r_refdef.view.colorscale;
10535         c[2] *= 2 * r_refdef.view.colorscale;
10536
10537         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10538                 c[3] *= r_wateralpha.value;
10539
10540         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10541         {
10542                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10543                 GL_DepthMask(false);
10544         }
10545         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10546         {
10547                 GL_BlendFunc(GL_ONE, GL_ONE);
10548                 GL_DepthMask(false);
10549         }
10550         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10551         {
10552                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10553                 GL_DepthMask(false);
10554         }
10555         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10556         {
10557                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10558                 GL_DepthMask(false);
10559         }
10560         else
10561         {
10562                 GL_BlendFunc(GL_ONE, GL_ZERO);
10563                 GL_DepthMask(writedepth);
10564         }
10565
10566         if (r_showsurfaces.integer == 3)
10567         {
10568                 rsurface.passcolor4f = NULL;
10569
10570                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10571                 {
10572                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10573
10574                         rsurface.passcolor4f = NULL;
10575                         rsurface.passcolor4f_vertexbuffer = 0;
10576                         rsurface.passcolor4f_bufferoffset = 0;
10577                 }
10578                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10579                 {
10580                         qboolean applycolor = true;
10581                         float one = 1.0;
10582
10583                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10584
10585                         r_refdef.lightmapintensity = 1;
10586                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10587                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10588                 }
10589                 else if (FAKELIGHT_ENABLED)
10590                 {
10591                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10592
10593                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10594                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10595                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10596                 }
10597                 else
10598                 {
10599                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10600
10601                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10602                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10603                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10604                 }
10605
10606                 if(!rsurface.passcolor4f)
10607                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10608
10609                 RSurf_DrawBatch_GL11_ApplyAmbient();
10610                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10611                 if(r_refdef.fogenabled)
10612                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10613                 RSurf_DrawBatch_GL11_ClampColor();
10614
10615                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10616                 R_SetupShader_Generic_NoTexture(false, false);
10617                 RSurf_DrawBatch();
10618         }
10619         else if (!r_refdef.view.showdebug)
10620         {
10621                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10622                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10623                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10624                 {
10625                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10626                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10627                 }
10628                 R_Mesh_PrepareVertices_Generic_Unlock();
10629                 RSurf_DrawBatch();
10630         }
10631         else if (r_showsurfaces.integer == 4)
10632         {
10633                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10634                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10635                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10636                 {
10637                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10638                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10639                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10640                 }
10641                 R_Mesh_PrepareVertices_Generic_Unlock();
10642                 RSurf_DrawBatch();
10643         }
10644         else if (r_showsurfaces.integer == 2)
10645         {
10646                 const int *e;
10647                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10648                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10649                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10650                 {
10651                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10652                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10653                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10654                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10655                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10656                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10657                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10658                 }
10659                 R_Mesh_PrepareVertices_Generic_Unlock();
10660                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10661         }
10662         else
10663         {
10664                 int texturesurfaceindex;
10665                 int k;
10666                 const msurface_t *surface;
10667                 float surfacecolor4f[4];
10668                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10669                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10670                 vi = 0;
10671                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10672                 {
10673                         surface = texturesurfacelist[texturesurfaceindex];
10674                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10675                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10676                         for (j = 0;j < surface->num_vertices;j++)
10677                         {
10678                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10679                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10680                                 vi++;
10681                         }
10682                 }
10683                 R_Mesh_PrepareVertices_Generic_Unlock();
10684                 RSurf_DrawBatch();
10685         }
10686 }
10687
10688 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10689 {
10690         CHECKGLERROR
10691         RSurf_SetupDepthAndCulling();
10692         if (r_showsurfaces.integer)
10693         {
10694                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10695                 return;
10696         }
10697         switch (vid.renderpath)
10698         {
10699         case RENDERPATH_GL20:
10700         case RENDERPATH_D3D9:
10701         case RENDERPATH_D3D10:
10702         case RENDERPATH_D3D11:
10703         case RENDERPATH_SOFT:
10704         case RENDERPATH_GLES2:
10705                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10706                 break;
10707         case RENDERPATH_GL13:
10708         case RENDERPATH_GLES1:
10709                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10710                 break;
10711         case RENDERPATH_GL11:
10712                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10713                 break;
10714         }
10715         CHECKGLERROR
10716 }
10717
10718 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10719 {
10720         CHECKGLERROR
10721         RSurf_SetupDepthAndCulling();
10722         if (r_showsurfaces.integer)
10723         {
10724                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10725                 return;
10726         }
10727         switch (vid.renderpath)
10728         {
10729         case RENDERPATH_GL20:
10730         case RENDERPATH_D3D9:
10731         case RENDERPATH_D3D10:
10732         case RENDERPATH_D3D11:
10733         case RENDERPATH_SOFT:
10734         case RENDERPATH_GLES2:
10735                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10736                 break;
10737         case RENDERPATH_GL13:
10738         case RENDERPATH_GLES1:
10739                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10740                 break;
10741         case RENDERPATH_GL11:
10742                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10743                 break;
10744         }
10745         CHECKGLERROR
10746 }
10747
10748 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10749 {
10750         int i, j;
10751         int texturenumsurfaces, endsurface;
10752         texture_t *texture;
10753         const msurface_t *surface;
10754         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10755
10756         // if the model is static it doesn't matter what value we give for
10757         // wantnormals and wanttangents, so this logic uses only rules applicable
10758         // to a model, knowing that they are meaningless otherwise
10759         if (ent == r_refdef.scene.worldentity)
10760                 RSurf_ActiveWorldEntity();
10761         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10762                 RSurf_ActiveModelEntity(ent, false, false, false);
10763         else
10764         {
10765                 switch (vid.renderpath)
10766                 {
10767                 case RENDERPATH_GL20:
10768                 case RENDERPATH_D3D9:
10769                 case RENDERPATH_D3D10:
10770                 case RENDERPATH_D3D11:
10771                 case RENDERPATH_SOFT:
10772                 case RENDERPATH_GLES2:
10773                         RSurf_ActiveModelEntity(ent, true, true, false);
10774                         break;
10775                 case RENDERPATH_GL11:
10776                 case RENDERPATH_GL13:
10777                 case RENDERPATH_GLES1:
10778                         RSurf_ActiveModelEntity(ent, true, false, false);
10779                         break;
10780                 }
10781         }
10782
10783         if (r_transparentdepthmasking.integer)
10784         {
10785                 qboolean setup = false;
10786                 for (i = 0;i < numsurfaces;i = j)
10787                 {
10788                         j = i + 1;
10789                         surface = rsurface.modelsurfaces + surfacelist[i];
10790                         texture = surface->texture;
10791                         rsurface.texture = R_GetCurrentTexture(texture);
10792                         rsurface.lightmaptexture = NULL;
10793                         rsurface.deluxemaptexture = NULL;
10794                         rsurface.uselightmaptexture = false;
10795                         // scan ahead until we find a different texture
10796                         endsurface = min(i + 1024, numsurfaces);
10797                         texturenumsurfaces = 0;
10798                         texturesurfacelist[texturenumsurfaces++] = surface;
10799                         for (;j < endsurface;j++)
10800                         {
10801                                 surface = rsurface.modelsurfaces + surfacelist[j];
10802                                 if (texture != surface->texture)
10803                                         break;
10804                                 texturesurfacelist[texturenumsurfaces++] = surface;
10805                         }
10806                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10807                                 continue;
10808                         // render the range of surfaces as depth
10809                         if (!setup)
10810                         {
10811                                 setup = true;
10812                                 GL_ColorMask(0,0,0,0);
10813                                 GL_Color(1,1,1,1);
10814                                 GL_DepthTest(true);
10815                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10816                                 GL_DepthMask(true);
10817 //                              R_Mesh_ResetTextureState();
10818                         }
10819                         RSurf_SetupDepthAndCulling();
10820                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10821                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
10822                         if (rsurface.batchvertex3fbuffer)
10823                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10824                         else
10825                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10826                         RSurf_DrawBatch();
10827                 }
10828                 if (setup)
10829                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10830         }
10831
10832         for (i = 0;i < numsurfaces;i = j)
10833         {
10834                 j = i + 1;
10835                 surface = rsurface.modelsurfaces + surfacelist[i];
10836                 texture = surface->texture;
10837                 rsurface.texture = R_GetCurrentTexture(texture);
10838                 // scan ahead until we find a different texture
10839                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10840                 texturenumsurfaces = 0;
10841                 texturesurfacelist[texturenumsurfaces++] = surface;
10842                 if(FAKELIGHT_ENABLED)
10843                 {
10844                         rsurface.lightmaptexture = NULL;
10845                         rsurface.deluxemaptexture = NULL;
10846                         rsurface.uselightmaptexture = false;
10847                         for (;j < endsurface;j++)
10848                         {
10849                                 surface = rsurface.modelsurfaces + surfacelist[j];
10850                                 if (texture != surface->texture)
10851                                         break;
10852                                 texturesurfacelist[texturenumsurfaces++] = surface;
10853                         }
10854                 }
10855                 else
10856                 {
10857                         rsurface.lightmaptexture = surface->lightmaptexture;
10858                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10859                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10860                         for (;j < endsurface;j++)
10861                         {
10862                                 surface = rsurface.modelsurfaces + surfacelist[j];
10863                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10864                                         break;
10865                                 texturesurfacelist[texturenumsurfaces++] = surface;
10866                         }
10867                 }
10868                 // render the range of surfaces
10869                 if (ent == r_refdef.scene.worldentity)
10870                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10871                 else
10872                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10873         }
10874         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10875 }
10876
10877 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10878 {
10879         // transparent surfaces get pushed off into the transparent queue
10880         int surfacelistindex;
10881         const msurface_t *surface;
10882         vec3_t tempcenter, center;
10883         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10884         {
10885                 surface = texturesurfacelist[surfacelistindex];
10886                 if (r_transparent_sortsurfacesbynearest.integer)
10887                 {
10888                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10889                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10890                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10891                 }
10892                 else
10893                 {
10894                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10895                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10896                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10897                 }
10898                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10899                 if (rsurface.entity->transparent_offset) // transparent offset
10900                 {
10901                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10902                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10903                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10904                 }
10905                 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);
10906         }
10907 }
10908
10909 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10910 {
10911         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10912                 return;
10913         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10914                 return;
10915         RSurf_SetupDepthAndCulling();
10916         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10917         if (rsurface.batchvertex3fbuffer)
10918                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10919         else
10920                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10921         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
10922         RSurf_DrawBatch();
10923 }
10924
10925 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10926 {
10927         CHECKGLERROR
10928         if (depthonly)
10929                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10930         else if (prepass)
10931         {
10932                 if (!rsurface.texture->currentnumlayers)
10933                         return;
10934                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10935                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10936                 else
10937                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10938         }
10939         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10940                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10941         else if (!rsurface.texture->currentnumlayers)
10942                 return;
10943         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10944         {
10945                 // in the deferred case, transparent surfaces were queued during prepass
10946                 if (!r_shadow_usingdeferredprepass)
10947                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10948         }
10949         else
10950         {
10951                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10952                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10953         }
10954         CHECKGLERROR
10955 }
10956
10957 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10958 {
10959         int i, j;
10960         texture_t *texture;
10961         R_FrameData_SetMark();
10962         // break the surface list down into batches by texture and use of lightmapping
10963         for (i = 0;i < numsurfaces;i = j)
10964         {
10965                 j = i + 1;
10966                 // texture is the base texture pointer, rsurface.texture is the
10967                 // current frame/skin the texture is directing us to use (for example
10968                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10969                 // use skin 1 instead)
10970                 texture = surfacelist[i]->texture;
10971                 rsurface.texture = R_GetCurrentTexture(texture);
10972                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10973                 {
10974                         // if this texture is not the kind we want, skip ahead to the next one
10975                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10976                                 ;
10977                         continue;
10978                 }
10979                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10980                 {
10981                         rsurface.lightmaptexture = NULL;
10982                         rsurface.deluxemaptexture = NULL;
10983                         rsurface.uselightmaptexture = false;
10984                         // simply scan ahead until we find a different texture or lightmap state
10985                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10986                                 ;
10987                 }
10988                 else
10989                 {
10990                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10991                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10992                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10993                         // simply scan ahead until we find a different texture or lightmap state
10994                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10995                                 ;
10996                 }
10997                 // render the range of surfaces
10998                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10999         }
11000         R_FrameData_ReturnToMark();
11001 }
11002
11003 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11004 {
11005         CHECKGLERROR
11006         if (depthonly)
11007                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11008         else if (prepass)
11009         {
11010                 if (!rsurface.texture->currentnumlayers)
11011                         return;
11012                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11013                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11014                 else
11015                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11016         }
11017         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11018                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11019         else if (!rsurface.texture->currentnumlayers)
11020                 return;
11021         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11022         {
11023                 // in the deferred case, transparent surfaces were queued during prepass
11024                 if (!r_shadow_usingdeferredprepass)
11025                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11026         }
11027         else
11028         {
11029                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11030                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11031         }
11032         CHECKGLERROR
11033 }
11034
11035 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11036 {
11037         int i, j;
11038         texture_t *texture;
11039         R_FrameData_SetMark();
11040         // break the surface list down into batches by texture and use of lightmapping
11041         for (i = 0;i < numsurfaces;i = j)
11042         {
11043                 j = i + 1;
11044                 // texture is the base texture pointer, rsurface.texture is the
11045                 // current frame/skin the texture is directing us to use (for example
11046                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11047                 // use skin 1 instead)
11048                 texture = surfacelist[i]->texture;
11049                 rsurface.texture = R_GetCurrentTexture(texture);
11050                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11051                 {
11052                         // if this texture is not the kind we want, skip ahead to the next one
11053                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11054                                 ;
11055                         continue;
11056                 }
11057                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11058                 {
11059                         rsurface.lightmaptexture = NULL;
11060                         rsurface.deluxemaptexture = NULL;
11061                         rsurface.uselightmaptexture = false;
11062                         // simply scan ahead until we find a different texture or lightmap state
11063                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11064                                 ;
11065                 }
11066                 else
11067                 {
11068                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11069                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11070                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11071                         // simply scan ahead until we find a different texture or lightmap state
11072                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11073                                 ;
11074                 }
11075                 // render the range of surfaces
11076                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11077         }
11078         R_FrameData_ReturnToMark();
11079 }
11080
11081 float locboxvertex3f[6*4*3] =
11082 {
11083         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11084         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11085         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11086         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11087         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11088         1,0,0, 0,0,0, 0,1,0, 1,1,0
11089 };
11090
11091 unsigned short locboxelements[6*2*3] =
11092 {
11093          0, 1, 2, 0, 2, 3,
11094          4, 5, 6, 4, 6, 7,
11095          8, 9,10, 8,10,11,
11096         12,13,14, 12,14,15,
11097         16,17,18, 16,18,19,
11098         20,21,22, 20,22,23
11099 };
11100
11101 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11102 {
11103         int i, j;
11104         cl_locnode_t *loc = (cl_locnode_t *)ent;
11105         vec3_t mins, size;
11106         float vertex3f[6*4*3];
11107         CHECKGLERROR
11108         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11109         GL_DepthMask(false);
11110         GL_DepthRange(0, 1);
11111         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11112         GL_DepthTest(true);
11113         GL_CullFace(GL_NONE);
11114         R_EntityMatrix(&identitymatrix);
11115
11116 //      R_Mesh_ResetTextureState();
11117
11118         i = surfacelist[0];
11119         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11120                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11121                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11122                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11123
11124         if (VectorCompare(loc->mins, loc->maxs))
11125         {
11126                 VectorSet(size, 2, 2, 2);
11127                 VectorMA(loc->mins, -0.5f, size, mins);
11128         }
11129         else
11130         {
11131                 VectorCopy(loc->mins, mins);
11132                 VectorSubtract(loc->maxs, loc->mins, size);
11133         }
11134
11135         for (i = 0;i < 6*4*3;)
11136                 for (j = 0;j < 3;j++, i++)
11137                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11138
11139         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11140         R_SetupShader_Generic_NoTexture(false, false);
11141         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11142 }
11143
11144 void R_DrawLocs(void)
11145 {
11146         int index;
11147         cl_locnode_t *loc, *nearestloc;
11148         vec3_t center;
11149         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11150         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11151         {
11152                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11153                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11154         }
11155 }
11156
11157 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11158 {
11159         if (decalsystem->decals)
11160                 Mem_Free(decalsystem->decals);
11161         memset(decalsystem, 0, sizeof(*decalsystem));
11162 }
11163
11164 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)
11165 {
11166         tridecal_t *decal;
11167         tridecal_t *decals;
11168         int i;
11169
11170         // expand or initialize the system
11171         if (decalsystem->maxdecals <= decalsystem->numdecals)
11172         {
11173                 decalsystem_t old = *decalsystem;
11174                 qboolean useshortelements;
11175                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11176                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11177                 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)));
11178                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11179                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11180                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11181                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11182                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11183                 if (decalsystem->numdecals)
11184                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11185                 if (old.decals)
11186                         Mem_Free(old.decals);
11187                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11188                         decalsystem->element3i[i] = i;
11189                 if (useshortelements)
11190                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11191                                 decalsystem->element3s[i] = i;
11192         }
11193
11194         // grab a decal and search for another free slot for the next one
11195         decals = decalsystem->decals;
11196         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11197         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11198                 ;
11199         decalsystem->freedecal = i;
11200         if (decalsystem->numdecals <= i)
11201                 decalsystem->numdecals = i + 1;
11202
11203         // initialize the decal
11204         decal->lived = 0;
11205         decal->triangleindex = triangleindex;
11206         decal->surfaceindex = surfaceindex;
11207         decal->decalsequence = decalsequence;
11208         decal->color4f[0][0] = c0[0];
11209         decal->color4f[0][1] = c0[1];
11210         decal->color4f[0][2] = c0[2];
11211         decal->color4f[0][3] = 1;
11212         decal->color4f[1][0] = c1[0];
11213         decal->color4f[1][1] = c1[1];
11214         decal->color4f[1][2] = c1[2];
11215         decal->color4f[1][3] = 1;
11216         decal->color4f[2][0] = c2[0];
11217         decal->color4f[2][1] = c2[1];
11218         decal->color4f[2][2] = c2[2];
11219         decal->color4f[2][3] = 1;
11220         decal->vertex3f[0][0] = v0[0];
11221         decal->vertex3f[0][1] = v0[1];
11222         decal->vertex3f[0][2] = v0[2];
11223         decal->vertex3f[1][0] = v1[0];
11224         decal->vertex3f[1][1] = v1[1];
11225         decal->vertex3f[1][2] = v1[2];
11226         decal->vertex3f[2][0] = v2[0];
11227         decal->vertex3f[2][1] = v2[1];
11228         decal->vertex3f[2][2] = v2[2];
11229         decal->texcoord2f[0][0] = t0[0];
11230         decal->texcoord2f[0][1] = t0[1];
11231         decal->texcoord2f[1][0] = t1[0];
11232         decal->texcoord2f[1][1] = t1[1];
11233         decal->texcoord2f[2][0] = t2[0];
11234         decal->texcoord2f[2][1] = t2[1];
11235         TriangleNormal(v0, v1, v2, decal->plane);
11236         VectorNormalize(decal->plane);
11237         decal->plane[3] = DotProduct(v0, decal->plane);
11238 }
11239
11240 extern cvar_t cl_decals_bias;
11241 extern cvar_t cl_decals_models;
11242 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11243 // baseparms, parms, temps
11244 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)
11245 {
11246         int cornerindex;
11247         int index;
11248         float v[9][3];
11249         const float *vertex3f;
11250         const float *normal3f;
11251         int numpoints;
11252         float points[2][9][3];
11253         float temp[3];
11254         float tc[9][2];
11255         float f;
11256         float c[9][4];
11257         const int *e;
11258
11259         e = rsurface.modelelement3i + 3*triangleindex;
11260
11261         vertex3f = rsurface.modelvertex3f;
11262         normal3f = rsurface.modelnormal3f;
11263
11264         if (normal3f)
11265         {
11266                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11267                 {
11268                         index = 3*e[cornerindex];
11269                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11270                 }
11271         }
11272         else
11273         {
11274                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11275                 {
11276                         index = 3*e[cornerindex];
11277                         VectorCopy(vertex3f + index, v[cornerindex]);
11278                 }
11279         }
11280
11281         // cull backfaces
11282         //TriangleNormal(v[0], v[1], v[2], normal);
11283         //if (DotProduct(normal, localnormal) < 0.0f)
11284         //      continue;
11285         // clip by each of the box planes formed from the projection matrix
11286         // if anything survives, we emit the decal
11287         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]);
11288         if (numpoints < 3)
11289                 return;
11290         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]);
11291         if (numpoints < 3)
11292                 return;
11293         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]);
11294         if (numpoints < 3)
11295                 return;
11296         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]);
11297         if (numpoints < 3)
11298                 return;
11299         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]);
11300         if (numpoints < 3)
11301                 return;
11302         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]);
11303         if (numpoints < 3)
11304                 return;
11305         // some part of the triangle survived, so we have to accept it...
11306         if (dynamic)
11307         {
11308                 // dynamic always uses the original triangle
11309                 numpoints = 3;
11310                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11311                 {
11312                         index = 3*e[cornerindex];
11313                         VectorCopy(vertex3f + index, v[cornerindex]);
11314                 }
11315         }
11316         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11317         {
11318                 // convert vertex positions to texcoords
11319                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11320                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11321                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11322                 // calculate distance fade from the projection origin
11323                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11324                 f = bound(0.0f, f, 1.0f);
11325                 c[cornerindex][0] = r * f;
11326                 c[cornerindex][1] = g * f;
11327                 c[cornerindex][2] = b * f;
11328                 c[cornerindex][3] = 1.0f;
11329                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11330         }
11331         if (dynamic)
11332                 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);
11333         else
11334                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11335                         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);
11336 }
11337 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)
11338 {
11339         matrix4x4_t projection;
11340         decalsystem_t *decalsystem;
11341         qboolean dynamic;
11342         dp_model_t *model;
11343         const msurface_t *surface;
11344         const msurface_t *surfaces;
11345         const int *surfacelist;
11346         const texture_t *texture;
11347         int numtriangles;
11348         int numsurfacelist;
11349         int surfacelistindex;
11350         int surfaceindex;
11351         int triangleindex;
11352         float localorigin[3];
11353         float localnormal[3];
11354         float localmins[3];
11355         float localmaxs[3];
11356         float localsize;
11357         //float normal[3];
11358         float planes[6][4];
11359         float angles[3];
11360         bih_t *bih;
11361         int bih_triangles_count;
11362         int bih_triangles[256];
11363         int bih_surfaces[256];
11364
11365         decalsystem = &ent->decalsystem;
11366         model = ent->model;
11367         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11368         {
11369                 R_DecalSystem_Reset(&ent->decalsystem);
11370                 return;
11371         }
11372
11373         if (!model->brush.data_leafs && !cl_decals_models.integer)
11374         {
11375                 if (decalsystem->model)
11376                         R_DecalSystem_Reset(decalsystem);
11377                 return;
11378         }
11379
11380         if (decalsystem->model != model)
11381                 R_DecalSystem_Reset(decalsystem);
11382         decalsystem->model = model;
11383
11384         RSurf_ActiveModelEntity(ent, true, false, false);
11385
11386         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11387         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11388         VectorNormalize(localnormal);
11389         localsize = worldsize*rsurface.inversematrixscale;
11390         localmins[0] = localorigin[0] - localsize;
11391         localmins[1] = localorigin[1] - localsize;
11392         localmins[2] = localorigin[2] - localsize;
11393         localmaxs[0] = localorigin[0] + localsize;
11394         localmaxs[1] = localorigin[1] + localsize;
11395         localmaxs[2] = localorigin[2] + localsize;
11396
11397         //VectorCopy(localnormal, planes[4]);
11398         //VectorVectors(planes[4], planes[2], planes[0]);
11399         AnglesFromVectors(angles, localnormal, NULL, false);
11400         AngleVectors(angles, planes[0], planes[2], planes[4]);
11401         VectorNegate(planes[0], planes[1]);
11402         VectorNegate(planes[2], planes[3]);
11403         VectorNegate(planes[4], planes[5]);
11404         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11405         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11406         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11407         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11408         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11409         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11410
11411 #if 1
11412 // works
11413 {
11414         matrix4x4_t forwardprojection;
11415         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11416         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11417 }
11418 #else
11419 // broken
11420 {
11421         float projectionvector[4][3];
11422         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11423         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11424         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11425         projectionvector[0][0] = planes[0][0] * ilocalsize;
11426         projectionvector[0][1] = planes[1][0] * ilocalsize;
11427         projectionvector[0][2] = planes[2][0] * ilocalsize;
11428         projectionvector[1][0] = planes[0][1] * ilocalsize;
11429         projectionvector[1][1] = planes[1][1] * ilocalsize;
11430         projectionvector[1][2] = planes[2][1] * ilocalsize;
11431         projectionvector[2][0] = planes[0][2] * ilocalsize;
11432         projectionvector[2][1] = planes[1][2] * ilocalsize;
11433         projectionvector[2][2] = planes[2][2] * ilocalsize;
11434         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11435         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11436         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11437         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11438 }
11439 #endif
11440
11441         dynamic = model->surfmesh.isanimated;
11442         numsurfacelist = model->nummodelsurfaces;
11443         surfacelist = model->sortedmodelsurfaces;
11444         surfaces = model->data_surfaces;
11445
11446         bih = NULL;
11447         bih_triangles_count = -1;
11448         if(!dynamic)
11449         {
11450                 if(model->render_bih.numleafs)
11451                         bih = &model->render_bih;
11452                 else if(model->collision_bih.numleafs)
11453                         bih = &model->collision_bih;
11454         }
11455         if(bih)
11456                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11457         if(bih_triangles_count == 0)
11458                 return;
11459         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11460                 return;
11461         if(bih_triangles_count > 0)
11462         {
11463                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11464                 {
11465                         surfaceindex = bih_surfaces[triangleindex];
11466                         surface = surfaces + surfaceindex;
11467                         texture = surface->texture;
11468                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11469                                 continue;
11470                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11471                                 continue;
11472                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11473                 }
11474         }
11475         else
11476         {
11477                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11478                 {
11479                         surfaceindex = surfacelist[surfacelistindex];
11480                         surface = surfaces + surfaceindex;
11481                         // check cull box first because it rejects more than any other check
11482                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11483                                 continue;
11484                         // skip transparent surfaces
11485                         texture = surface->texture;
11486                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11487                                 continue;
11488                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11489                                 continue;
11490                         numtriangles = surface->num_triangles;
11491                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11492                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11493                 }
11494         }
11495 }
11496
11497 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11498 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)
11499 {
11500         int renderentityindex;
11501         float worldmins[3];
11502         float worldmaxs[3];
11503         entity_render_t *ent;
11504
11505         if (!cl_decals_newsystem.integer)
11506                 return;
11507
11508         worldmins[0] = worldorigin[0] - worldsize;
11509         worldmins[1] = worldorigin[1] - worldsize;
11510         worldmins[2] = worldorigin[2] - worldsize;
11511         worldmaxs[0] = worldorigin[0] + worldsize;
11512         worldmaxs[1] = worldorigin[1] + worldsize;
11513         worldmaxs[2] = worldorigin[2] + worldsize;
11514
11515         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11516
11517         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11518         {
11519                 ent = r_refdef.scene.entities[renderentityindex];
11520                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11521                         continue;
11522
11523                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11524         }
11525 }
11526
11527 typedef struct r_decalsystem_splatqueue_s
11528 {
11529         vec3_t worldorigin;
11530         vec3_t worldnormal;
11531         float color[4];
11532         float tcrange[4];
11533         float worldsize;
11534         int decalsequence;
11535 }
11536 r_decalsystem_splatqueue_t;
11537
11538 int r_decalsystem_numqueued = 0;
11539 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11540
11541 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)
11542 {
11543         r_decalsystem_splatqueue_t *queue;
11544
11545         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11546                 return;
11547
11548         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11549         VectorCopy(worldorigin, queue->worldorigin);
11550         VectorCopy(worldnormal, queue->worldnormal);
11551         Vector4Set(queue->color, r, g, b, a);
11552         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11553         queue->worldsize = worldsize;
11554         queue->decalsequence = cl.decalsequence++;
11555 }
11556
11557 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11558 {
11559         int i;
11560         r_decalsystem_splatqueue_t *queue;
11561
11562         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11563                 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);
11564         r_decalsystem_numqueued = 0;
11565 }
11566
11567 extern cvar_t cl_decals_max;
11568 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11569 {
11570         int i;
11571         decalsystem_t *decalsystem = &ent->decalsystem;
11572         int numdecals;
11573         int killsequence;
11574         tridecal_t *decal;
11575         float frametime;
11576         float lifetime;
11577
11578         if (!decalsystem->numdecals)
11579                 return;
11580
11581         if (r_showsurfaces.integer)
11582                 return;
11583
11584         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11585         {
11586                 R_DecalSystem_Reset(decalsystem);
11587                 return;
11588         }
11589
11590         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11591         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11592
11593         if (decalsystem->lastupdatetime)
11594                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11595         else
11596                 frametime = 0;
11597         decalsystem->lastupdatetime = r_refdef.scene.time;
11598         numdecals = decalsystem->numdecals;
11599
11600         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11601         {
11602                 if (decal->color4f[0][3])
11603                 {
11604                         decal->lived += frametime;
11605                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11606                         {
11607                                 memset(decal, 0, sizeof(*decal));
11608                                 if (decalsystem->freedecal > i)
11609                                         decalsystem->freedecal = i;
11610                         }
11611                 }
11612         }
11613         decal = decalsystem->decals;
11614         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11615                 numdecals--;
11616
11617         // collapse the array by shuffling the tail decals into the gaps
11618         for (;;)
11619         {
11620                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11621                         decalsystem->freedecal++;
11622                 if (decalsystem->freedecal == numdecals)
11623                         break;
11624                 decal[decalsystem->freedecal] = decal[--numdecals];
11625         }
11626
11627         decalsystem->numdecals = numdecals;
11628
11629         if (numdecals <= 0)
11630         {
11631                 // if there are no decals left, reset decalsystem
11632                 R_DecalSystem_Reset(decalsystem);
11633         }
11634 }
11635
11636 extern skinframe_t *decalskinframe;
11637 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11638 {
11639         int i;
11640         decalsystem_t *decalsystem = &ent->decalsystem;
11641         int numdecals;
11642         tridecal_t *decal;
11643         float faderate;
11644         float alpha;
11645         float *v3f;
11646         float *c4f;
11647         float *t2f;
11648         const int *e;
11649         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11650         int numtris = 0;
11651
11652         numdecals = decalsystem->numdecals;
11653         if (!numdecals)
11654                 return;
11655
11656         if (r_showsurfaces.integer)
11657                 return;
11658
11659         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11660         {
11661                 R_DecalSystem_Reset(decalsystem);
11662                 return;
11663         }
11664
11665         // if the model is static it doesn't matter what value we give for
11666         // wantnormals and wanttangents, so this logic uses only rules applicable
11667         // to a model, knowing that they are meaningless otherwise
11668         if (ent == r_refdef.scene.worldentity)
11669                 RSurf_ActiveWorldEntity();
11670         else
11671                 RSurf_ActiveModelEntity(ent, false, false, false);
11672
11673         decalsystem->lastupdatetime = r_refdef.scene.time;
11674
11675         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11676
11677         // update vertex positions for animated models
11678         v3f = decalsystem->vertex3f;
11679         c4f = decalsystem->color4f;
11680         t2f = decalsystem->texcoord2f;
11681         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11682         {
11683                 if (!decal->color4f[0][3])
11684                         continue;
11685
11686                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11687                         continue;
11688
11689                 // skip backfaces
11690                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11691                         continue;
11692
11693                 // update color values for fading decals
11694                 if (decal->lived >= cl_decals_time.value)
11695                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11696                 else
11697                         alpha = 1.0f;
11698
11699                 c4f[ 0] = decal->color4f[0][0] * alpha;
11700                 c4f[ 1] = decal->color4f[0][1] * alpha;
11701                 c4f[ 2] = decal->color4f[0][2] * alpha;
11702                 c4f[ 3] = 1;
11703                 c4f[ 4] = decal->color4f[1][0] * alpha;
11704                 c4f[ 5] = decal->color4f[1][1] * alpha;
11705                 c4f[ 6] = decal->color4f[1][2] * alpha;
11706                 c4f[ 7] = 1;
11707                 c4f[ 8] = decal->color4f[2][0] * alpha;
11708                 c4f[ 9] = decal->color4f[2][1] * alpha;
11709                 c4f[10] = decal->color4f[2][2] * alpha;
11710                 c4f[11] = 1;
11711
11712                 t2f[0] = decal->texcoord2f[0][0];
11713                 t2f[1] = decal->texcoord2f[0][1];
11714                 t2f[2] = decal->texcoord2f[1][0];
11715                 t2f[3] = decal->texcoord2f[1][1];
11716                 t2f[4] = decal->texcoord2f[2][0];
11717                 t2f[5] = decal->texcoord2f[2][1];
11718
11719                 // update vertex positions for animated models
11720                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11721                 {
11722                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11723                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11724                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11725                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11726                 }
11727                 else
11728                 {
11729                         VectorCopy(decal->vertex3f[0], v3f);
11730                         VectorCopy(decal->vertex3f[1], v3f + 3);
11731                         VectorCopy(decal->vertex3f[2], v3f + 6);
11732                 }
11733
11734                 if (r_refdef.fogenabled)
11735                 {
11736                         alpha = RSurf_FogVertex(v3f);
11737                         VectorScale(c4f, alpha, c4f);
11738                         alpha = RSurf_FogVertex(v3f + 3);
11739                         VectorScale(c4f + 4, alpha, c4f + 4);
11740                         alpha = RSurf_FogVertex(v3f + 6);
11741                         VectorScale(c4f + 8, alpha, c4f + 8);
11742                 }
11743
11744                 v3f += 9;
11745                 c4f += 12;
11746                 t2f += 6;
11747                 numtris++;
11748         }
11749
11750         if (numtris > 0)
11751         {
11752                 r_refdef.stats.drawndecals += numtris;
11753
11754                 // now render the decals all at once
11755                 // (this assumes they all use one particle font texture!)
11756                 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);
11757 //              R_Mesh_ResetTextureState();
11758                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11759                 GL_DepthMask(false);
11760                 GL_DepthRange(0, 1);
11761                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11762                 GL_DepthTest(true);
11763                 GL_CullFace(GL_NONE);
11764                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11765                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11766                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11767         }
11768 }
11769
11770 static void R_DrawModelDecals(void)
11771 {
11772         int i, numdecals;
11773
11774         // fade faster when there are too many decals
11775         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11776         for (i = 0;i < r_refdef.scene.numentities;i++)
11777                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11778
11779         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11780         for (i = 0;i < r_refdef.scene.numentities;i++)
11781                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11782                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11783
11784         R_DecalSystem_ApplySplatEntitiesQueue();
11785
11786         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11787         for (i = 0;i < r_refdef.scene.numentities;i++)
11788                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11789
11790         r_refdef.stats.totaldecals += numdecals;
11791
11792         if (r_showsurfaces.integer)
11793                 return;
11794
11795         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11796
11797         for (i = 0;i < r_refdef.scene.numentities;i++)
11798         {
11799                 if (!r_refdef.viewcache.entityvisible[i])
11800                         continue;
11801                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11802                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11803         }
11804 }
11805
11806 extern cvar_t mod_collision_bih;
11807 static void R_DrawDebugModel(void)
11808 {
11809         entity_render_t *ent = rsurface.entity;
11810         int i, j, k, l, flagsmask;
11811         const msurface_t *surface;
11812         dp_model_t *model = ent->model;
11813         vec3_t v;
11814
11815         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11816                 return;
11817
11818         if (r_showoverdraw.value > 0)
11819         {
11820                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11821                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11822                 R_SetupShader_Generic_NoTexture(false, false);
11823                 GL_DepthTest(false);
11824                 GL_DepthMask(false);
11825                 GL_DepthRange(0, 1);
11826                 GL_BlendFunc(GL_ONE, GL_ONE);
11827                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11828                 {
11829                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11830                                 continue;
11831                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11832                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11833                         {
11834                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11835                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11836                                 if (!rsurface.texture->currentlayers->depthmask)
11837                                         GL_Color(c, 0, 0, 1.0f);
11838                                 else if (ent == r_refdef.scene.worldentity)
11839                                         GL_Color(c, c, c, 1.0f);
11840                                 else
11841                                         GL_Color(0, c, 0, 1.0f);
11842                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11843                                 RSurf_DrawBatch();
11844                         }
11845                 }
11846                 rsurface.texture = NULL;
11847         }
11848
11849         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11850
11851 //      R_Mesh_ResetTextureState();
11852         R_SetupShader_Generic_NoTexture(false, false);
11853         GL_DepthRange(0, 1);
11854         GL_DepthTest(!r_showdisabledepthtest.integer);
11855         GL_DepthMask(false);
11856         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11857
11858         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11859         {
11860                 int triangleindex;
11861                 int bihleafindex;
11862                 qboolean cullbox = false;
11863                 const q3mbrush_t *brush;
11864                 const bih_t *bih = &model->collision_bih;
11865                 const bih_leaf_t *bihleaf;
11866                 float vertex3f[3][3];
11867                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11868                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11869                 {
11870                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11871                                 continue;
11872                         switch (bihleaf->type)
11873                         {
11874                         case BIH_BRUSH:
11875                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11876                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11877                                 {
11878                                         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);
11879                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11880                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11881                                 }
11882                                 break;
11883                         case BIH_COLLISIONTRIANGLE:
11884                                 triangleindex = bihleaf->itemindex;
11885                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11886                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11887                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11888                                 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);
11889                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11890                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11891                                 break;
11892                         case BIH_RENDERTRIANGLE:
11893                                 triangleindex = bihleaf->itemindex;
11894                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11895                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11896                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11897                                 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);
11898                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11899                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11900                                 break;
11901                         }
11902                 }
11903         }
11904
11905         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11906
11907 #ifndef USE_GLES2
11908         if (r_showtris.integer && qglPolygonMode)
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                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11921                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11922                 {
11923                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11924                                 continue;
11925                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11926                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11927                         {
11928                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11929                                 if (!rsurface.texture->currentlayers->depthmask)
11930                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11931                                 else if (ent == r_refdef.scene.worldentity)
11932                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11933                                 else
11934                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11935                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11936                                 RSurf_DrawBatch();
11937                         }
11938                 }
11939                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11940                 rsurface.texture = NULL;
11941         }
11942
11943         if (r_shownormals.value != 0 && qglBegin)
11944         {
11945                 if (r_showdisabledepthtest.integer)
11946                 {
11947                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11948                         GL_DepthMask(false);
11949                 }
11950                 else
11951                 {
11952                         GL_BlendFunc(GL_ONE, GL_ZERO);
11953                         GL_DepthMask(true);
11954                 }
11955                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11956                 {
11957                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11958                                 continue;
11959                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11960                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11961                         {
11962                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11963                                 qglBegin(GL_LINES);
11964                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11965                                 {
11966                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11967                                         {
11968                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11969                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11970                                                 qglVertex3f(v[0], v[1], v[2]);
11971                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11972                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11973                                                 qglVertex3f(v[0], v[1], v[2]);
11974                                         }
11975                                 }
11976                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11977                                 {
11978                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11979                                         {
11980                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11981                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11982                                                 qglVertex3f(v[0], v[1], v[2]);
11983                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11984                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11985                                                 qglVertex3f(v[0], v[1], v[2]);
11986                                         }
11987                                 }
11988                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11989                                 {
11990                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11991                                         {
11992                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11993                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11994                                                 qglVertex3f(v[0], v[1], v[2]);
11995                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11996                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11997                                                 qglVertex3f(v[0], v[1], v[2]);
11998                                         }
11999                                 }
12000                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12001                                 {
12002                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12003                                         {
12004                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12005                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12006                                                 qglVertex3f(v[0], v[1], v[2]);
12007                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12008                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12009                                                 qglVertex3f(v[0], v[1], v[2]);
12010                                         }
12011                                 }
12012                                 qglEnd();
12013                                 CHECKGLERROR
12014                         }
12015                 }
12016                 rsurface.texture = NULL;
12017         }
12018 #endif
12019 }
12020
12021 int r_maxsurfacelist = 0;
12022 const msurface_t **r_surfacelist = NULL;
12023 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12024 {
12025         int i, j, endj, flagsmask;
12026         dp_model_t *model = r_refdef.scene.worldmodel;
12027         msurface_t *surfaces;
12028         unsigned char *update;
12029         int numsurfacelist = 0;
12030         if (model == NULL)
12031                 return;
12032
12033         if (r_maxsurfacelist < model->num_surfaces)
12034         {
12035                 r_maxsurfacelist = model->num_surfaces;
12036                 if (r_surfacelist)
12037                         Mem_Free((msurface_t**)r_surfacelist);
12038                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12039         }
12040
12041         RSurf_ActiveWorldEntity();
12042
12043         surfaces = model->data_surfaces;
12044         update = model->brushq1.lightmapupdateflags;
12045
12046         // update light styles on this submodel
12047         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12048         {
12049                 model_brush_lightstyleinfo_t *style;
12050                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12051                 {
12052                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12053                         {
12054                                 int *list = style->surfacelist;
12055                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12056                                 for (j = 0;j < style->numsurfaces;j++)
12057                                         update[list[j]] = true;
12058                         }
12059                 }
12060         }
12061
12062         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12063
12064         if (debug)
12065         {
12066                 R_DrawDebugModel();
12067                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12068                 return;
12069         }
12070
12071         rsurface.lightmaptexture = NULL;
12072         rsurface.deluxemaptexture = NULL;
12073         rsurface.uselightmaptexture = false;
12074         rsurface.texture = NULL;
12075         rsurface.rtlight = NULL;
12076         numsurfacelist = 0;
12077         // add visible surfaces to draw list
12078         for (i = 0;i < model->nummodelsurfaces;i++)
12079         {
12080                 j = model->sortedmodelsurfaces[i];
12081                 if (r_refdef.viewcache.world_surfacevisible[j])
12082                         r_surfacelist[numsurfacelist++] = surfaces + j;
12083         }
12084         // update lightmaps if needed
12085         if (model->brushq1.firstrender)
12086         {
12087                 model->brushq1.firstrender = false;
12088                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12089                         if (update[j])
12090                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12091         }
12092         else if (update)
12093         {
12094                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12095                         if (r_refdef.viewcache.world_surfacevisible[j])
12096                                 if (update[j])
12097                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12098         }
12099         // don't do anything if there were no surfaces
12100         if (!numsurfacelist)
12101         {
12102                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12103                 return;
12104         }
12105         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12106
12107         // add to stats if desired
12108         if (r_speeds.integer && !skysurfaces && !depthonly)
12109         {
12110                 r_refdef.stats.world_surfaces += numsurfacelist;
12111                 for (j = 0;j < numsurfacelist;j++)
12112                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12113         }
12114
12115         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12116 }
12117
12118 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12119 {
12120         int i, j, endj, flagsmask;
12121         dp_model_t *model = ent->model;
12122         msurface_t *surfaces;
12123         unsigned char *update;
12124         int numsurfacelist = 0;
12125         if (model == NULL)
12126                 return;
12127
12128         if (r_maxsurfacelist < model->num_surfaces)
12129         {
12130                 r_maxsurfacelist = model->num_surfaces;
12131                 if (r_surfacelist)
12132                         Mem_Free((msurface_t **)r_surfacelist);
12133                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12134         }
12135
12136         // if the model is static it doesn't matter what value we give for
12137         // wantnormals and wanttangents, so this logic uses only rules applicable
12138         // to a model, knowing that they are meaningless otherwise
12139         if (ent == r_refdef.scene.worldentity)
12140                 RSurf_ActiveWorldEntity();
12141         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12142                 RSurf_ActiveModelEntity(ent, false, false, false);
12143         else if (prepass)
12144                 RSurf_ActiveModelEntity(ent, true, true, true);
12145         else if (depthonly)
12146         {
12147                 switch (vid.renderpath)
12148                 {
12149                 case RENDERPATH_GL20:
12150                 case RENDERPATH_D3D9:
12151                 case RENDERPATH_D3D10:
12152                 case RENDERPATH_D3D11:
12153                 case RENDERPATH_SOFT:
12154                 case RENDERPATH_GLES2:
12155                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12156                         break;
12157                 case RENDERPATH_GL11:
12158                 case RENDERPATH_GL13:
12159                 case RENDERPATH_GLES1:
12160                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12161                         break;
12162                 }
12163         }
12164         else
12165         {
12166                 switch (vid.renderpath)
12167                 {
12168                 case RENDERPATH_GL20:
12169                 case RENDERPATH_D3D9:
12170                 case RENDERPATH_D3D10:
12171                 case RENDERPATH_D3D11:
12172                 case RENDERPATH_SOFT:
12173                 case RENDERPATH_GLES2:
12174                         RSurf_ActiveModelEntity(ent, true, true, false);
12175                         break;
12176                 case RENDERPATH_GL11:
12177                 case RENDERPATH_GL13:
12178                 case RENDERPATH_GLES1:
12179                         RSurf_ActiveModelEntity(ent, true, false, false);
12180                         break;
12181                 }
12182         }
12183
12184         surfaces = model->data_surfaces;
12185         update = model->brushq1.lightmapupdateflags;
12186
12187         // update light styles
12188         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12189         {
12190                 model_brush_lightstyleinfo_t *style;
12191                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12192                 {
12193                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12194                         {
12195                                 int *list = style->surfacelist;
12196                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12197                                 for (j = 0;j < style->numsurfaces;j++)
12198                                         update[list[j]] = true;
12199                         }
12200                 }
12201         }
12202
12203         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12204
12205         if (debug)
12206         {
12207                 R_DrawDebugModel();
12208                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12209                 return;
12210         }
12211
12212         rsurface.lightmaptexture = NULL;
12213         rsurface.deluxemaptexture = NULL;
12214         rsurface.uselightmaptexture = false;
12215         rsurface.texture = NULL;
12216         rsurface.rtlight = NULL;
12217         numsurfacelist = 0;
12218         // add visible surfaces to draw list
12219         for (i = 0;i < model->nummodelsurfaces;i++)
12220                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12221         // don't do anything if there were no surfaces
12222         if (!numsurfacelist)
12223         {
12224                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12225                 return;
12226         }
12227         // update lightmaps if needed
12228         if (update)
12229         {
12230                 int updated = 0;
12231                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12232                 {
12233                         if (update[j])
12234                         {
12235                                 updated++;
12236                                 R_BuildLightMap(ent, surfaces + j);
12237                         }
12238                 }
12239         }
12240
12241         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12242
12243         // add to stats if desired
12244         if (r_speeds.integer && !skysurfaces && !depthonly)
12245         {
12246                 r_refdef.stats.entities_surfaces += numsurfacelist;
12247                 for (j = 0;j < numsurfacelist;j++)
12248                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12249         }
12250
12251         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12252 }
12253
12254 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12255 {
12256         static texture_t texture;
12257         static msurface_t surface;
12258         const msurface_t *surfacelist = &surface;
12259
12260         // fake enough texture and surface state to render this geometry
12261
12262         texture.update_lastrenderframe = -1; // regenerate this texture
12263         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12264         texture.currentskinframe = skinframe;
12265         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12266         texture.offsetmapping = OFFSETMAPPING_OFF;
12267         texture.offsetscale = 1;
12268         texture.specularscalemod = 1;
12269         texture.specularpowermod = 1;
12270         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12271         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12272         // JUST GREP FOR "specularscalemod = 1".
12273
12274         surface.texture = &texture;
12275         surface.num_triangles = numtriangles;
12276         surface.num_firsttriangle = firsttriangle;
12277         surface.num_vertices = numvertices;
12278         surface.num_firstvertex = firstvertex;
12279
12280         // now render it
12281         rsurface.texture = R_GetCurrentTexture(surface.texture);
12282         rsurface.lightmaptexture = NULL;
12283         rsurface.deluxemaptexture = NULL;
12284         rsurface.uselightmaptexture = false;
12285         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12286 }
12287
12288 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)
12289 {
12290         static msurface_t surface;
12291         const msurface_t *surfacelist = &surface;
12292
12293         // fake enough texture and surface state to render this geometry
12294         surface.texture = texture;
12295         surface.num_triangles = numtriangles;
12296         surface.num_firsttriangle = firsttriangle;
12297         surface.num_vertices = numvertices;
12298         surface.num_firstvertex = firstvertex;
12299
12300         // now render it
12301         rsurface.texture = R_GetCurrentTexture(surface.texture);
12302         rsurface.lightmaptexture = NULL;
12303         rsurface.deluxemaptexture = NULL;
12304         rsurface.uselightmaptexture = false;
12305         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12306 }