]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
17dc8e5e489cb17a36cfff177e7724e6e78c038d
[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_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)"};
166 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
167 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)"};
168 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
169 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)"};
170 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)"};
171 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
172 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"};
173 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."};
174 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
175 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)"};
176 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)"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182 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)"};
183
184 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)"};
185 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
186 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"};
187 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
188 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
189 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
190 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"};
191 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"};
192 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)"};
193
194 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
195 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
196 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
197 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
198
199 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
200 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
201
202 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
203 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
204 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
205 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
206 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
207 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
208
209 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
210 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
211 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
212 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
213 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
214 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
215 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
216 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
217 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
218 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
219
220 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"};
221
222 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"};
223
224 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
225
226 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
227
228 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)"};
229 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)"};
230
231 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
232 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"};
233
234 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."};
235
236 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)"};
237
238 extern cvar_t v_glslgamma;
239 extern cvar_t v_glslgamma_2d;
240
241 extern qboolean v_flipped_state;
242
243 r_framebufferstate_t r_fb;
244
245 /// shadow volume bsp struct with automatically growing nodes buffer
246 svbsp_t r_svbsp;
247
248 rtexture_t *r_texture_blanknormalmap;
249 rtexture_t *r_texture_white;
250 rtexture_t *r_texture_grey128;
251 rtexture_t *r_texture_black;
252 rtexture_t *r_texture_notexture;
253 rtexture_t *r_texture_whitecube;
254 rtexture_t *r_texture_normalizationcube;
255 rtexture_t *r_texture_fogattenuation;
256 rtexture_t *r_texture_fogheighttexture;
257 rtexture_t *r_texture_gammaramps;
258 unsigned int r_texture_gammaramps_serial;
259 //rtexture_t *r_texture_fogintensity;
260 rtexture_t *r_texture_reflectcube;
261
262 // TODO: hash lookups?
263 typedef struct cubemapinfo_s
264 {
265         char basename[64];
266         rtexture_t *texture;
267 }
268 cubemapinfo_t;
269
270 int r_texture_numcubemaps;
271 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
272
273 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
274 unsigned int r_numqueries;
275 unsigned int r_maxqueries;
276
277 typedef struct r_qwskincache_s
278 {
279         char name[MAX_QPATH];
280         skinframe_t *skinframe;
281 }
282 r_qwskincache_t;
283
284 static r_qwskincache_t *r_qwskincache;
285 static int r_qwskincache_size;
286
287 /// vertex coordinates for a quad that covers the screen exactly
288 extern const float r_screenvertex3f[12];
289 extern const float r_d3dscreenvertex3f[12];
290 const float r_screenvertex3f[12] =
291 {
292         0, 0, 0,
293         1, 0, 0,
294         1, 1, 0,
295         0, 1, 0
296 };
297 const float r_d3dscreenvertex3f[12] =
298 {
299         0, 1, 0,
300         1, 1, 0,
301         1, 0, 0,
302         0, 0, 0
303 };
304
305 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
306 {
307         int i;
308         for (i = 0;i < verts;i++)
309         {
310                 out[0] = in[0] * r;
311                 out[1] = in[1] * g;
312                 out[2] = in[2] * b;
313                 out[3] = in[3];
314                 in += 4;
315                 out += 4;
316         }
317 }
318
319 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
320 {
321         int i;
322         for (i = 0;i < verts;i++)
323         {
324                 out[0] = r;
325                 out[1] = g;
326                 out[2] = b;
327                 out[3] = a;
328                 out += 4;
329         }
330 }
331
332 // FIXME: move this to client?
333 void FOG_clear(void)
334 {
335         if (gamemode == GAME_NEHAHRA)
336         {
337                 Cvar_Set("gl_fogenable", "0");
338                 Cvar_Set("gl_fogdensity", "0.2");
339                 Cvar_Set("gl_fogred", "0.3");
340                 Cvar_Set("gl_foggreen", "0.3");
341                 Cvar_Set("gl_fogblue", "0.3");
342         }
343         r_refdef.fog_density = 0;
344         r_refdef.fog_red = 0;
345         r_refdef.fog_green = 0;
346         r_refdef.fog_blue = 0;
347         r_refdef.fog_alpha = 1;
348         r_refdef.fog_start = 0;
349         r_refdef.fog_end = 16384;
350         r_refdef.fog_height = 1<<30;
351         r_refdef.fog_fadedepth = 128;
352         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
353 }
354
355 static void R_BuildBlankTextures(void)
356 {
357         unsigned char data[4];
358         data[2] = 128; // normal X
359         data[1] = 128; // normal Y
360         data[0] = 255; // normal Z
361         data[3] = 255; // height
362         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363         data[0] = 255;
364         data[1] = 255;
365         data[2] = 255;
366         data[3] = 255;
367         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
368         data[0] = 128;
369         data[1] = 128;
370         data[2] = 128;
371         data[3] = 255;
372         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
373         data[0] = 0;
374         data[1] = 0;
375         data[2] = 0;
376         data[3] = 255;
377         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
378 }
379
380 static void R_BuildNoTexture(void)
381 {
382         int x, y;
383         unsigned char pix[16][16][4];
384         // this makes a light grey/dark grey checkerboard texture
385         for (y = 0;y < 16;y++)
386         {
387                 for (x = 0;x < 16;x++)
388                 {
389                         if ((y < 8) ^ (x < 8))
390                         {
391                                 pix[y][x][0] = 128;
392                                 pix[y][x][1] = 128;
393                                 pix[y][x][2] = 128;
394                                 pix[y][x][3] = 255;
395                         }
396                         else
397                         {
398                                 pix[y][x][0] = 64;
399                                 pix[y][x][1] = 64;
400                                 pix[y][x][2] = 64;
401                                 pix[y][x][3] = 255;
402                         }
403                 }
404         }
405         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
406 }
407
408 static void R_BuildWhiteCube(void)
409 {
410         unsigned char data[6*1*1*4];
411         memset(data, 255, sizeof(data));
412         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
413 }
414
415 static void R_BuildNormalizationCube(void)
416 {
417         int x, y, side;
418         vec3_t v;
419         vec_t s, t, intensity;
420 #define NORMSIZE 64
421         unsigned char *data;
422         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
423         for (side = 0;side < 6;side++)
424         {
425                 for (y = 0;y < NORMSIZE;y++)
426                 {
427                         for (x = 0;x < NORMSIZE;x++)
428                         {
429                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
430                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
431                                 switch(side)
432                                 {
433                                 default:
434                                 case 0:
435                                         v[0] = 1;
436                                         v[1] = -t;
437                                         v[2] = -s;
438                                         break;
439                                 case 1:
440                                         v[0] = -1;
441                                         v[1] = -t;
442                                         v[2] = s;
443                                         break;
444                                 case 2:
445                                         v[0] = s;
446                                         v[1] = 1;
447                                         v[2] = t;
448                                         break;
449                                 case 3:
450                                         v[0] = s;
451                                         v[1] = -1;
452                                         v[2] = -t;
453                                         break;
454                                 case 4:
455                                         v[0] = s;
456                                         v[1] = -t;
457                                         v[2] = 1;
458                                         break;
459                                 case 5:
460                                         v[0] = -s;
461                                         v[1] = -t;
462                                         v[2] = -1;
463                                         break;
464                                 }
465                                 intensity = 127.0f / sqrt(DotProduct(v, v));
466                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
467                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
468                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
469                                 data[((side*64+y)*64+x)*4+3] = 255;
470                         }
471                 }
472         }
473         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
474         Mem_Free(data);
475 }
476
477 static void R_BuildFogTexture(void)
478 {
479         int x, b;
480 #define FOGWIDTH 256
481         unsigned char data1[FOGWIDTH][4];
482         //unsigned char data2[FOGWIDTH][4];
483         double d, r, alpha;
484
485         r_refdef.fogmasktable_start = r_refdef.fog_start;
486         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
487         r_refdef.fogmasktable_range = r_refdef.fogrange;
488         r_refdef.fogmasktable_density = r_refdef.fog_density;
489
490         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
491         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
492         {
493                 d = (x * r - r_refdef.fogmasktable_start);
494                 if(developer_extra.integer)
495                         Con_DPrintf("%f ", d);
496                 d = max(0, d);
497                 if (r_fog_exp2.integer)
498                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
499                 else
500                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
501                 if(developer_extra.integer)
502                         Con_DPrintf(" : %f ", alpha);
503                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
504                 if(developer_extra.integer)
505                         Con_DPrintf(" = %f\n", alpha);
506                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
507         }
508
509         for (x = 0;x < FOGWIDTH;x++)
510         {
511                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
512                 data1[x][0] = b;
513                 data1[x][1] = b;
514                 data1[x][2] = b;
515                 data1[x][3] = 255;
516                 //data2[x][0] = 255 - b;
517                 //data2[x][1] = 255 - b;
518                 //data2[x][2] = 255 - b;
519                 //data2[x][3] = 255;
520         }
521         if (r_texture_fogattenuation)
522         {
523                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
524                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
525         }
526         else
527         {
528                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
529                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
530         }
531 }
532
533 static void R_BuildFogHeightTexture(void)
534 {
535         unsigned char *inpixels;
536         int size;
537         int x;
538         int y;
539         int j;
540         float c[4];
541         float f;
542         inpixels = NULL;
543         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
544         if (r_refdef.fogheighttexturename[0])
545                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
546         if (!inpixels)
547         {
548                 r_refdef.fog_height_tablesize = 0;
549                 if (r_texture_fogheighttexture)
550                         R_FreeTexture(r_texture_fogheighttexture);
551                 r_texture_fogheighttexture = NULL;
552                 if (r_refdef.fog_height_table2d)
553                         Mem_Free(r_refdef.fog_height_table2d);
554                 r_refdef.fog_height_table2d = NULL;
555                 if (r_refdef.fog_height_table1d)
556                         Mem_Free(r_refdef.fog_height_table1d);
557                 r_refdef.fog_height_table1d = NULL;
558                 return;
559         }
560         size = image_width;
561         r_refdef.fog_height_tablesize = size;
562         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
563         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
564         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
565         Mem_Free(inpixels);
566         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
567         // average fog color table accounting for every fog layer between a point
568         // and the camera.  (Note: attenuation is handled separately!)
569         for (y = 0;y < size;y++)
570         {
571                 for (x = 0;x < size;x++)
572                 {
573                         Vector4Clear(c);
574                         f = 0;
575                         if (x < y)
576                         {
577                                 for (j = x;j <= y;j++)
578                                 {
579                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
580                                         f++;
581                                 }
582                         }
583                         else
584                         {
585                                 for (j = x;j >= y;j--)
586                                 {
587                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
588                                         f++;
589                                 }
590                         }
591                         f = 1.0f / f;
592                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
593                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
594                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
595                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
596                 }
597         }
598         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
599 }
600
601 //=======================================================================================================================================================
602
603 static const char *builtinshaderstring =
604 #include "shader_glsl.h"
605 ;
606
607 const char *builtinhlslshaderstring =
608 #include "shader_hlsl.h"
609 ;
610
611 char *glslshaderstring = NULL;
612 char *hlslshaderstring = NULL;
613
614 //=======================================================================================================================================================
615
616 typedef struct shaderpermutationinfo_s
617 {
618         const char *pretext;
619         const char *name;
620 }
621 shaderpermutationinfo_t;
622
623 typedef struct shadermodeinfo_s
624 {
625         const char *vertexfilename;
626         const char *geometryfilename;
627         const char *fragmentfilename;
628         const char *pretext;
629         const char *name;
630 }
631 shadermodeinfo_t;
632
633 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
634 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
635 {
636         {"#define USEDIFFUSE\n", " diffuse"},
637         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
638         {"#define USEVIEWTINT\n", " viewtint"},
639         {"#define USECOLORMAPPING\n", " colormapping"},
640         {"#define USESATURATION\n", " saturation"},
641         {"#define USEFOGINSIDE\n", " foginside"},
642         {"#define USEFOGOUTSIDE\n", " fogoutside"},
643         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
644         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
645         {"#define USEGAMMARAMPS\n", " gammaramps"},
646         {"#define USECUBEFILTER\n", " cubefilter"},
647         {"#define USEGLOW\n", " glow"},
648         {"#define USEBLOOM\n", " bloom"},
649         {"#define USESPECULAR\n", " specular"},
650         {"#define USEPOSTPROCESSING\n", " postprocessing"},
651         {"#define USEREFLECTION\n", " reflection"},
652         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
653         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
654         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
655         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
656         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
657         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
658         {"#define USEALPHAKILL\n", " alphakill"},
659         {"#define USEREFLECTCUBE\n", " reflectcube"},
660         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
661         {"#define USEBOUNCEGRID\n", " bouncegrid"},
662         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
663         {"#define USETRIPPY\n", " trippy"},
664         {"#define USEDEPTHRGB\n", " depthrgb"},
665         {"#define USEALPHAGENVERTEX\n", "alphagenvertex"}
666 };
667
668 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
669 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
670 {
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
689 };
690
691 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
692 {
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
711 };
712
713 struct r_glsl_permutation_s;
714 typedef struct r_glsl_permutation_s
715 {
716         /// hash lookup data
717         struct r_glsl_permutation_s *hashnext;
718         unsigned int mode;
719         unsigned int permutation;
720
721         /// indicates if we have tried compiling this permutation already
722         qboolean compiled;
723         /// 0 if compilation failed
724         int program;
725         // texture units assigned to each detected uniform
726         int tex_Texture_First;
727         int tex_Texture_Second;
728         int tex_Texture_GammaRamps;
729         int tex_Texture_Normal;
730         int tex_Texture_Color;
731         int tex_Texture_Gloss;
732         int tex_Texture_Glow;
733         int tex_Texture_SecondaryNormal;
734         int tex_Texture_SecondaryColor;
735         int tex_Texture_SecondaryGloss;
736         int tex_Texture_SecondaryGlow;
737         int tex_Texture_Pants;
738         int tex_Texture_Shirt;
739         int tex_Texture_FogHeightTexture;
740         int tex_Texture_FogMask;
741         int tex_Texture_Lightmap;
742         int tex_Texture_Deluxemap;
743         int tex_Texture_Attenuation;
744         int tex_Texture_Cube;
745         int tex_Texture_Refraction;
746         int tex_Texture_Reflection;
747         int tex_Texture_ShadowMap2D;
748         int tex_Texture_CubeProjection;
749         int tex_Texture_ScreenNormalMap;
750         int tex_Texture_ScreenDiffuse;
751         int tex_Texture_ScreenSpecular;
752         int tex_Texture_ReflectMask;
753         int tex_Texture_ReflectCube;
754         int tex_Texture_BounceGrid;
755         /// locations of detected uniforms in program object, or -1 if not found
756         int loc_Texture_First;
757         int loc_Texture_Second;
758         int loc_Texture_GammaRamps;
759         int loc_Texture_Normal;
760         int loc_Texture_Color;
761         int loc_Texture_Gloss;
762         int loc_Texture_Glow;
763         int loc_Texture_SecondaryNormal;
764         int loc_Texture_SecondaryColor;
765         int loc_Texture_SecondaryGloss;
766         int loc_Texture_SecondaryGlow;
767         int loc_Texture_Pants;
768         int loc_Texture_Shirt;
769         int loc_Texture_FogHeightTexture;
770         int loc_Texture_FogMask;
771         int loc_Texture_Lightmap;
772         int loc_Texture_Deluxemap;
773         int loc_Texture_Attenuation;
774         int loc_Texture_Cube;
775         int loc_Texture_Refraction;
776         int loc_Texture_Reflection;
777         int loc_Texture_ShadowMap2D;
778         int loc_Texture_CubeProjection;
779         int loc_Texture_ScreenNormalMap;
780         int loc_Texture_ScreenDiffuse;
781         int loc_Texture_ScreenSpecular;
782         int loc_Texture_ReflectMask;
783         int loc_Texture_ReflectCube;
784         int loc_Texture_BounceGrid;
785         int loc_Alpha;
786         int loc_BloomBlur_Parameters;
787         int loc_ClientTime;
788         int loc_Color_Ambient;
789         int loc_Color_Diffuse;
790         int loc_Color_Specular;
791         int loc_Color_Glow;
792         int loc_Color_Pants;
793         int loc_Color_Shirt;
794         int loc_DeferredColor_Ambient;
795         int loc_DeferredColor_Diffuse;
796         int loc_DeferredColor_Specular;
797         int loc_DeferredMod_Diffuse;
798         int loc_DeferredMod_Specular;
799         int loc_DistortScaleRefractReflect;
800         int loc_EyePosition;
801         int loc_FogColor;
802         int loc_FogHeightFade;
803         int loc_FogPlane;
804         int loc_FogPlaneViewDist;
805         int loc_FogRangeRecip;
806         int loc_LightColor;
807         int loc_LightDir;
808         int loc_LightPosition;
809         int loc_OffsetMapping_ScaleSteps;
810         int loc_OffsetMapping_LodDistance;
811         int loc_OffsetMapping_Bias;
812         int loc_PixelSize;
813         int loc_ReflectColor;
814         int loc_ReflectFactor;
815         int loc_ReflectOffset;
816         int loc_RefractColor;
817         int loc_Saturation;
818         int loc_ScreenCenterRefractReflect;
819         int loc_ScreenScaleRefractReflect;
820         int loc_ScreenToDepth;
821         int loc_ShadowMap_Parameters;
822         int loc_ShadowMap_TextureScale;
823         int loc_SpecularPower;
824         int loc_UserVec1;
825         int loc_UserVec2;
826         int loc_UserVec3;
827         int loc_UserVec4;
828         int loc_ViewTintColor;
829         int loc_ViewToLight;
830         int loc_ModelToLight;
831         int loc_TexMatrix;
832         int loc_BackgroundTexMatrix;
833         int loc_ModelViewProjectionMatrix;
834         int loc_ModelViewMatrix;
835         int loc_PixelToScreenTexCoord;
836         int loc_ModelToReflectCube;
837         int loc_ShadowMapMatrix;
838         int loc_BloomColorSubtract;
839         int loc_NormalmapScrollBlend;
840         int loc_BounceGridMatrix;
841         int loc_BounceGridIntensity;
842 }
843 r_glsl_permutation_t;
844
845 #define SHADERPERMUTATION_HASHSIZE 256
846
847
848 // non-degradable "lightweight" shader parameters to keep the permutations simpler
849 // these can NOT degrade! only use for simple stuff
850 enum
851 {
852         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
853         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
854         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
855         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
856         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
857         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
858         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
859         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
860         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
861         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
862         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
863         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
864         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
865 };
866 #define SHADERSTATICPARMS_COUNT 13
867
868 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
869 static int shaderstaticparms_count = 0;
870
871 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
872 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
873
874 extern qboolean r_shadow_shadowmapsampler;
875 extern int r_shadow_shadowmappcf;
876 qboolean R_CompileShader_CheckStaticParms(void)
877 {
878         static int r_compileshader_staticparms_save[1];
879         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
880         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
881
882         // detect all
883         if (r_glsl_saturation_redcompensate.integer)
884                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
885         if (r_glsl_vertextextureblend_usebothalphas.integer)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
887         if (r_shadow_glossexact.integer)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
889         if (r_glsl_postprocess.integer)
890         {
891                 if (r_glsl_postprocess_uservec1_enable.integer)
892                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
893                 if (r_glsl_postprocess_uservec2_enable.integer)
894                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
895                 if (r_glsl_postprocess_uservec3_enable.integer)
896                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
897                 if (r_glsl_postprocess_uservec4_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
899         }
900         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
901                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
902
903         if (r_shadow_shadowmapsampler)
904                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
905         if (r_shadow_shadowmappcf > 1)
906                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
907         else if (r_shadow_shadowmappcf)
908                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
909         if (r_celshading.integer)
910                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
911         if (r_celoutlines.integer)
912                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
913
914         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
915 }
916
917 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
918         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
919                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
920         else \
921                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
922 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
923 {
924         shaderstaticparms_count = 0;
925
926         // emit all
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
936         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
937         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
938         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
939         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
940 }
941
942 /// information about each possible shader permutation
943 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
944 /// currently selected permutation
945 r_glsl_permutation_t *r_glsl_permutation;
946 /// storage for permutations linked in the hash table
947 memexpandablearray_t r_glsl_permutationarray;
948
949 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
950 {
951         //unsigned int hashdepth = 0;
952         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
953         r_glsl_permutation_t *p;
954         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
955         {
956                 if (p->mode == mode && p->permutation == permutation)
957                 {
958                         //if (hashdepth > 10)
959                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
960                         return p;
961                 }
962                 //hashdepth++;
963         }
964         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
965         p->mode = mode;
966         p->permutation = permutation;
967         p->hashnext = r_glsl_permutationhash[mode][hashindex];
968         r_glsl_permutationhash[mode][hashindex] = p;
969         //if (hashdepth > 10)
970         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
971         return p;
972 }
973
974 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
975 {
976         char *shaderstring;
977         if (!filename || !filename[0])
978                 return NULL;
979         if (!strcmp(filename, "glsl/default.glsl"))
980         {
981                 if (!glslshaderstring)
982                 {
983                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
984                         if (glslshaderstring)
985                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
986                         else
987                                 glslshaderstring = (char *)builtinshaderstring;
988                 }
989                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
990                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
991                 return shaderstring;
992         }
993         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
994         if (shaderstring)
995         {
996                 if (printfromdisknotice)
997                         Con_DPrintf("from disk %s... ", filename);
998                 return shaderstring;
999         }
1000         return shaderstring;
1001 }
1002
1003 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1004 {
1005         int i;
1006         int sampler;
1007         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1008         char *vertexstring, *geometrystring, *fragmentstring;
1009         char permutationname[256];
1010         int vertstrings_count = 0;
1011         int geomstrings_count = 0;
1012         int fragstrings_count = 0;
1013         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1014         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1015         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1016
1017         if (p->compiled)
1018                 return;
1019         p->compiled = true;
1020         p->program = 0;
1021
1022         permutationname[0] = 0;
1023         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1024         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1025         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1026
1027         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1028
1029         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1030         if(vid.support.gl20shaders130)
1031         {
1032                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1033                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1034                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1035                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1036                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1037                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1038         }
1039
1040         // the first pretext is which type of shader to compile as
1041         // (later these will all be bound together as a program object)
1042         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1043         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1044         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1045
1046         // the second pretext is the mode (for example a light source)
1047         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1048         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1049         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1050         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1051
1052         // now add all the permutation pretexts
1053         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1054         {
1055                 if (permutation & (1<<i))
1056                 {
1057                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1058                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1059                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1060                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1061                 }
1062                 else
1063                 {
1064                         // keep line numbers correct
1065                         vertstrings_list[vertstrings_count++] = "\n";
1066                         geomstrings_list[geomstrings_count++] = "\n";
1067                         fragstrings_list[fragstrings_count++] = "\n";
1068                 }
1069         }
1070
1071         // add static parms
1072         R_CompileShader_AddStaticParms(mode, permutation);
1073         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1074         vertstrings_count += shaderstaticparms_count;
1075         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1076         geomstrings_count += shaderstaticparms_count;
1077         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1078         fragstrings_count += shaderstaticparms_count;
1079
1080         // now append the shader text itself
1081         vertstrings_list[vertstrings_count++] = vertexstring;
1082         geomstrings_list[geomstrings_count++] = geometrystring;
1083         fragstrings_list[fragstrings_count++] = fragmentstring;
1084
1085         // if any sources were NULL, clear the respective list
1086         if (!vertexstring)
1087                 vertstrings_count = 0;
1088         if (!geometrystring)
1089                 geomstrings_count = 0;
1090         if (!fragmentstring)
1091                 fragstrings_count = 0;
1092
1093         // compile the shader program
1094         if (vertstrings_count + geomstrings_count + fragstrings_count)
1095                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1096         if (p->program)
1097         {
1098                 CHECKGLERROR
1099                 qglUseProgram(p->program);CHECKGLERROR
1100                 // look up all the uniform variable names we care about, so we don't
1101                 // have to look them up every time we set them
1102
1103                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1104                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1105                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1106                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1107                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1108                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1109                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1110                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1111                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1112                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1113                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1114                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1115                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1116                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1117                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1118                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1119                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1120                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1121                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1122                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1123                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1124                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1125                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1126                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1127                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1128                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1129                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1130                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1131                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1132                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1133                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1134                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1135                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1136                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1137                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1138                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1139                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1140                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1141                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1142                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1143                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1144                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1145                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1146                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1147                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1148                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1149                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1150                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1151                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1152                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1153                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1154                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1155                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1156                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1157                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1158                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1159                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1160                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1161                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1162                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1163                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1164                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1165                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1166                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1167                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1168                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1169                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1170                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1171                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1172                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1173                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1174                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1175                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1176                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1177                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1178                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1179                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1180                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1181                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1182                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1183                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1184                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1185                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1186                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1187                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1188                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1189                 // initialize the samplers to refer to the texture units we use
1190                 p->tex_Texture_First = -1;
1191                 p->tex_Texture_Second = -1;
1192                 p->tex_Texture_GammaRamps = -1;
1193                 p->tex_Texture_Normal = -1;
1194                 p->tex_Texture_Color = -1;
1195                 p->tex_Texture_Gloss = -1;
1196                 p->tex_Texture_Glow = -1;
1197                 p->tex_Texture_SecondaryNormal = -1;
1198                 p->tex_Texture_SecondaryColor = -1;
1199                 p->tex_Texture_SecondaryGloss = -1;
1200                 p->tex_Texture_SecondaryGlow = -1;
1201                 p->tex_Texture_Pants = -1;
1202                 p->tex_Texture_Shirt = -1;
1203                 p->tex_Texture_FogHeightTexture = -1;
1204                 p->tex_Texture_FogMask = -1;
1205                 p->tex_Texture_Lightmap = -1;
1206                 p->tex_Texture_Deluxemap = -1;
1207                 p->tex_Texture_Attenuation = -1;
1208                 p->tex_Texture_Cube = -1;
1209                 p->tex_Texture_Refraction = -1;
1210                 p->tex_Texture_Reflection = -1;
1211                 p->tex_Texture_ShadowMap2D = -1;
1212                 p->tex_Texture_CubeProjection = -1;
1213                 p->tex_Texture_ScreenNormalMap = -1;
1214                 p->tex_Texture_ScreenDiffuse = -1;
1215                 p->tex_Texture_ScreenSpecular = -1;
1216                 p->tex_Texture_ReflectMask = -1;
1217                 p->tex_Texture_ReflectCube = -1;
1218                 p->tex_Texture_BounceGrid = -1;
1219                 sampler = 0;
1220                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1221                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1222                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1223                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1224                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1225                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1226                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1227                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1228                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1229                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1230                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1231                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1232                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1233                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1234                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1235                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1236                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1237                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1238                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1239                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1240                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1241                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1242                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1243                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1244                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1245                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1246                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1247                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1248                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1249                 CHECKGLERROR
1250                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1251         }
1252         else
1253                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1254
1255         // free the strings
1256         if (vertexstring)
1257                 Mem_Free(vertexstring);
1258         if (geometrystring)
1259                 Mem_Free(geometrystring);
1260         if (fragmentstring)
1261                 Mem_Free(fragmentstring);
1262 }
1263
1264 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1265 {
1266         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1267         if (r_glsl_permutation != perm)
1268         {
1269                 r_glsl_permutation = perm;
1270                 if (!r_glsl_permutation->program)
1271                 {
1272                         if (!r_glsl_permutation->compiled)
1273                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1274                         if (!r_glsl_permutation->program)
1275                         {
1276                                 // remove features until we find a valid permutation
1277                                 int i;
1278                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1279                                 {
1280                                         // reduce i more quickly whenever it would not remove any bits
1281                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1282                                         if (!(permutation & j))
1283                                                 continue;
1284                                         permutation -= j;
1285                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1286                                         if (!r_glsl_permutation->compiled)
1287                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1288                                         if (r_glsl_permutation->program)
1289                                                 break;
1290                                 }
1291                                 if (i >= SHADERPERMUTATION_COUNT)
1292                                 {
1293                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1294                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1295                                         qglUseProgram(0);CHECKGLERROR
1296                                         return; // no bit left to clear, entire mode is broken
1297                                 }
1298                         }
1299                 }
1300                 CHECKGLERROR
1301                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1302         }
1303         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1304         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1305         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1306 }
1307
1308 #ifdef SUPPORTD3D
1309
1310 #ifdef SUPPORTD3D
1311 #include <d3d9.h>
1312 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1313 extern D3DCAPS9 vid_d3d9caps;
1314 #endif
1315
1316 struct r_hlsl_permutation_s;
1317 typedef struct r_hlsl_permutation_s
1318 {
1319         /// hash lookup data
1320         struct r_hlsl_permutation_s *hashnext;
1321         unsigned int mode;
1322         unsigned int permutation;
1323
1324         /// indicates if we have tried compiling this permutation already
1325         qboolean compiled;
1326         /// NULL if compilation failed
1327         IDirect3DVertexShader9 *vertexshader;
1328         IDirect3DPixelShader9 *pixelshader;
1329 }
1330 r_hlsl_permutation_t;
1331
1332 typedef enum D3DVSREGISTER_e
1333 {
1334         D3DVSREGISTER_TexMatrix = 0, // float4x4
1335         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1336         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1337         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1338         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1339         D3DVSREGISTER_ModelToLight = 20, // float4x4
1340         D3DVSREGISTER_EyePosition = 24,
1341         D3DVSREGISTER_FogPlane = 25,
1342         D3DVSREGISTER_LightDir = 26,
1343         D3DVSREGISTER_LightPosition = 27,
1344 }
1345 D3DVSREGISTER_t;
1346
1347 typedef enum D3DPSREGISTER_e
1348 {
1349         D3DPSREGISTER_Alpha = 0,
1350         D3DPSREGISTER_BloomBlur_Parameters = 1,
1351         D3DPSREGISTER_ClientTime = 2,
1352         D3DPSREGISTER_Color_Ambient = 3,
1353         D3DPSREGISTER_Color_Diffuse = 4,
1354         D3DPSREGISTER_Color_Specular = 5,
1355         D3DPSREGISTER_Color_Glow = 6,
1356         D3DPSREGISTER_Color_Pants = 7,
1357         D3DPSREGISTER_Color_Shirt = 8,
1358         D3DPSREGISTER_DeferredColor_Ambient = 9,
1359         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1360         D3DPSREGISTER_DeferredColor_Specular = 11,
1361         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1362         D3DPSREGISTER_DeferredMod_Specular = 13,
1363         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1364         D3DPSREGISTER_EyePosition = 15, // unused
1365         D3DPSREGISTER_FogColor = 16,
1366         D3DPSREGISTER_FogHeightFade = 17,
1367         D3DPSREGISTER_FogPlane = 18,
1368         D3DPSREGISTER_FogPlaneViewDist = 19,
1369         D3DPSREGISTER_FogRangeRecip = 20,
1370         D3DPSREGISTER_LightColor = 21,
1371         D3DPSREGISTER_LightDir = 22, // unused
1372         D3DPSREGISTER_LightPosition = 23,
1373         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1374         D3DPSREGISTER_PixelSize = 25,
1375         D3DPSREGISTER_ReflectColor = 26,
1376         D3DPSREGISTER_ReflectFactor = 27,
1377         D3DPSREGISTER_ReflectOffset = 28,
1378         D3DPSREGISTER_RefractColor = 29,
1379         D3DPSREGISTER_Saturation = 30,
1380         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1381         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1382         D3DPSREGISTER_ScreenToDepth = 33,
1383         D3DPSREGISTER_ShadowMap_Parameters = 34,
1384         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1385         D3DPSREGISTER_SpecularPower = 36,
1386         D3DPSREGISTER_UserVec1 = 37,
1387         D3DPSREGISTER_UserVec2 = 38,
1388         D3DPSREGISTER_UserVec3 = 39,
1389         D3DPSREGISTER_UserVec4 = 40,
1390         D3DPSREGISTER_ViewTintColor = 41,
1391         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1392         D3DPSREGISTER_BloomColorSubtract = 43,
1393         D3DPSREGISTER_ViewToLight = 44, // float4x4
1394         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1395         D3DPSREGISTER_NormalmapScrollBlend = 52,
1396         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1397         D3DPSREGISTER_OffsetMapping_Bias = 54,
1398         // next at 54
1399 }
1400 D3DPSREGISTER_t;
1401
1402 /// information about each possible shader permutation
1403 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1404 /// currently selected permutation
1405 r_hlsl_permutation_t *r_hlsl_permutation;
1406 /// storage for permutations linked in the hash table
1407 memexpandablearray_t r_hlsl_permutationarray;
1408
1409 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1410 {
1411         //unsigned int hashdepth = 0;
1412         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1413         r_hlsl_permutation_t *p;
1414         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1415         {
1416                 if (p->mode == mode && p->permutation == permutation)
1417                 {
1418                         //if (hashdepth > 10)
1419                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1420                         return p;
1421                 }
1422                 //hashdepth++;
1423         }
1424         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1425         p->mode = mode;
1426         p->permutation = permutation;
1427         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1428         r_hlsl_permutationhash[mode][hashindex] = p;
1429         //if (hashdepth > 10)
1430         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1431         return p;
1432 }
1433
1434 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1435 {
1436         char *shaderstring;
1437         if (!filename || !filename[0])
1438                 return NULL;
1439         if (!strcmp(filename, "hlsl/default.hlsl"))
1440         {
1441                 if (!hlslshaderstring)
1442                 {
1443                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1444                         if (hlslshaderstring)
1445                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1446                         else
1447                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1448                 }
1449                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1450                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1451                 return shaderstring;
1452         }
1453         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1454         if (shaderstring)
1455         {
1456                 if (printfromdisknotice)
1457                         Con_DPrintf("from disk %s... ", filename);
1458                 return shaderstring;
1459         }
1460         return shaderstring;
1461 }
1462
1463 #include <d3dx9.h>
1464 //#include <d3dx9shader.h>
1465 //#include <d3dx9mesh.h>
1466
1467 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1468 {
1469         DWORD *vsbin = NULL;
1470         DWORD *psbin = NULL;
1471         fs_offset_t vsbinsize;
1472         fs_offset_t psbinsize;
1473 //      IDirect3DVertexShader9 *vs = NULL;
1474 //      IDirect3DPixelShader9 *ps = NULL;
1475         ID3DXBuffer *vslog = NULL;
1476         ID3DXBuffer *vsbuffer = NULL;
1477         ID3DXConstantTable *vsconstanttable = NULL;
1478         ID3DXBuffer *pslog = NULL;
1479         ID3DXBuffer *psbuffer = NULL;
1480         ID3DXConstantTable *psconstanttable = NULL;
1481         int vsresult = 0;
1482         int psresult = 0;
1483         char temp[MAX_INPUTLINE];
1484         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1485         char vabuf[1024];
1486         qboolean debugshader = gl_paranoid.integer != 0;
1487         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1488         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1489         if (!debugshader)
1490         {
1491                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1492                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1493         }
1494         if ((!vsbin && vertstring) || (!psbin && fragstring))
1495         {
1496                 const char* dllnames_d3dx9 [] =
1497                 {
1498                         "d3dx9_43.dll",
1499                         "d3dx9_42.dll",
1500                         "d3dx9_41.dll",
1501                         "d3dx9_40.dll",
1502                         "d3dx9_39.dll",
1503                         "d3dx9_38.dll",
1504                         "d3dx9_37.dll",
1505                         "d3dx9_36.dll",
1506                         "d3dx9_35.dll",
1507                         "d3dx9_34.dll",
1508                         "d3dx9_33.dll",
1509                         "d3dx9_32.dll",
1510                         "d3dx9_31.dll",
1511                         "d3dx9_30.dll",
1512                         "d3dx9_29.dll",
1513                         "d3dx9_28.dll",
1514                         "d3dx9_27.dll",
1515                         "d3dx9_26.dll",
1516                         "d3dx9_25.dll",
1517                         "d3dx9_24.dll",
1518                         NULL
1519                 };
1520                 dllhandle_t d3dx9_dll = NULL;
1521                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1522                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1523                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1524                 dllfunction_t d3dx9_dllfuncs[] =
1525                 {
1526                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1527                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1528                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1529                         {NULL, NULL}
1530                 };
1531                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1532                 {
1533                         DWORD shaderflags = 0;
1534                         if (debugshader)
1535                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1536                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1537                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1538                         if (vertstring && vertstring[0])
1539                         {
1540                                 if (debugshader)
1541                                 {
1542                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1543                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1544                                 }
1545                                 else
1546                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1547                                 if (vsbuffer)
1548                                 {
1549                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1550                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1551                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1552                                         ID3DXBuffer_Release(vsbuffer);
1553                                 }
1554                                 if (vslog)
1555                                 {
1556                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1557                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1558                                         ID3DXBuffer_Release(vslog);
1559                                 }
1560                         }
1561                         if (fragstring && fragstring[0])
1562                         {
1563                                 if (debugshader)
1564                                 {
1565                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1566                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1567                                 }
1568                                 else
1569                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1570                                 if (psbuffer)
1571                                 {
1572                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1573                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1574                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1575                                         ID3DXBuffer_Release(psbuffer);
1576                                 }
1577                                 if (pslog)
1578                                 {
1579                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1580                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1581                                         ID3DXBuffer_Release(pslog);
1582                                 }
1583                         }
1584                         Sys_UnloadLibrary(&d3dx9_dll);
1585                 }
1586                 else
1587                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1588         }
1589         if (vsbin && psbin)
1590         {
1591                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1592                 if (FAILED(vsresult))
1593                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1594                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1595                 if (FAILED(psresult))
1596                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1597         }
1598         // free the shader data
1599         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1600         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1601 }
1602
1603 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1604 {
1605         int i;
1606         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1607         int vertstring_length = 0;
1608         int geomstring_length = 0;
1609         int fragstring_length = 0;
1610         char *t;
1611         char *vertexstring, *geometrystring, *fragmentstring;
1612         char *vertstring, *geomstring, *fragstring;
1613         char permutationname[256];
1614         char cachename[256];
1615         int vertstrings_count = 0;
1616         int geomstrings_count = 0;
1617         int fragstrings_count = 0;
1618         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1619         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1620         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1621
1622         if (p->compiled)
1623                 return;
1624         p->compiled = true;
1625         p->vertexshader = NULL;
1626         p->pixelshader = NULL;
1627
1628         permutationname[0] = 0;
1629         cachename[0] = 0;
1630         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1631         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1632         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1633
1634         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1635         strlcat(cachename, "hlsl/", sizeof(cachename));
1636
1637         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1638         vertstrings_count = 0;
1639         geomstrings_count = 0;
1640         fragstrings_count = 0;
1641         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1642         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1643         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1644
1645         // the first pretext is which type of shader to compile as
1646         // (later these will all be bound together as a program object)
1647         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1648         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1649         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1650
1651         // the second pretext is the mode (for example a light source)
1652         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1653         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1654         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1655         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1656         strlcat(cachename, modeinfo->name, sizeof(cachename));
1657
1658         // now add all the permutation pretexts
1659         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1660         {
1661                 if (permutation & (1<<i))
1662                 {
1663                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1664                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1665                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1666                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1667                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1668                 }
1669                 else
1670                 {
1671                         // keep line numbers correct
1672                         vertstrings_list[vertstrings_count++] = "\n";
1673                         geomstrings_list[geomstrings_count++] = "\n";
1674                         fragstrings_list[fragstrings_count++] = "\n";
1675                 }
1676         }
1677
1678         // add static parms
1679         R_CompileShader_AddStaticParms(mode, permutation);
1680         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1681         vertstrings_count += shaderstaticparms_count;
1682         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1683         geomstrings_count += shaderstaticparms_count;
1684         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1685         fragstrings_count += shaderstaticparms_count;
1686
1687         // replace spaces in the cachename with _ characters
1688         for (i = 0;cachename[i];i++)
1689                 if (cachename[i] == ' ')
1690                         cachename[i] = '_';
1691
1692         // now append the shader text itself
1693         vertstrings_list[vertstrings_count++] = vertexstring;
1694         geomstrings_list[geomstrings_count++] = geometrystring;
1695         fragstrings_list[fragstrings_count++] = fragmentstring;
1696
1697         // if any sources were NULL, clear the respective list
1698         if (!vertexstring)
1699                 vertstrings_count = 0;
1700         if (!geometrystring)
1701                 geomstrings_count = 0;
1702         if (!fragmentstring)
1703                 fragstrings_count = 0;
1704
1705         vertstring_length = 0;
1706         for (i = 0;i < vertstrings_count;i++)
1707                 vertstring_length += strlen(vertstrings_list[i]);
1708         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1709         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1710                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1711
1712         geomstring_length = 0;
1713         for (i = 0;i < geomstrings_count;i++)
1714                 geomstring_length += strlen(geomstrings_list[i]);
1715         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1716         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1717                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1718
1719         fragstring_length = 0;
1720         for (i = 0;i < fragstrings_count;i++)
1721                 fragstring_length += strlen(fragstrings_list[i]);
1722         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1723         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1724                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1725
1726         // try to load the cached shader, or generate one
1727         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1728
1729         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1730                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1731         else
1732                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1733
1734         // free the strings
1735         if (vertstring)
1736                 Mem_Free(vertstring);
1737         if (geomstring)
1738                 Mem_Free(geomstring);
1739         if (fragstring)
1740                 Mem_Free(fragstring);
1741         if (vertexstring)
1742                 Mem_Free(vertexstring);
1743         if (geometrystring)
1744                 Mem_Free(geometrystring);
1745         if (fragmentstring)
1746                 Mem_Free(fragmentstring);
1747 }
1748
1749 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1750 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1751 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);}
1752 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);}
1753 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);}
1754 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);}
1755
1756 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1757 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1758 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);}
1759 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);}
1760 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);}
1761 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);}
1762
1763 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1764 {
1765         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1766         if (r_hlsl_permutation != perm)
1767         {
1768                 r_hlsl_permutation = perm;
1769                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1770                 {
1771                         if (!r_hlsl_permutation->compiled)
1772                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1773                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1774                         {
1775                                 // remove features until we find a valid permutation
1776                                 int i;
1777                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1778                                 {
1779                                         // reduce i more quickly whenever it would not remove any bits
1780                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1781                                         if (!(permutation & j))
1782                                                 continue;
1783                                         permutation -= j;
1784                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1785                                         if (!r_hlsl_permutation->compiled)
1786                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1787                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1788                                                 break;
1789                                 }
1790                                 if (i >= SHADERPERMUTATION_COUNT)
1791                                 {
1792                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1793                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1794                                         return; // no bit left to clear, entire mode is broken
1795                                 }
1796                         }
1797                 }
1798                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1799                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1800         }
1801         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1802         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1803         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1804 }
1805 #endif
1806
1807 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1808 {
1809         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1810         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1811         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1812         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1813 }
1814
1815 void R_GLSL_Restart_f(void)
1816 {
1817         unsigned int i, limit;
1818         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1819                 Mem_Free(glslshaderstring);
1820         glslshaderstring = NULL;
1821         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1822                 Mem_Free(hlslshaderstring);
1823         hlslshaderstring = NULL;
1824         switch(vid.renderpath)
1825         {
1826         case RENDERPATH_D3D9:
1827 #ifdef SUPPORTD3D
1828                 {
1829                         r_hlsl_permutation_t *p;
1830                         r_hlsl_permutation = NULL;
1831                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1832                         for (i = 0;i < limit;i++)
1833                         {
1834                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1835                                 {
1836                                         if (p->vertexshader)
1837                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1838                                         if (p->pixelshader)
1839                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1840                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1841                                 }
1842                         }
1843                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1844                 }
1845 #endif
1846                 break;
1847         case RENDERPATH_D3D10:
1848                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1849                 break;
1850         case RENDERPATH_D3D11:
1851                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1852                 break;
1853         case RENDERPATH_GL20:
1854         case RENDERPATH_GLES2:
1855                 {
1856                         r_glsl_permutation_t *p;
1857                         r_glsl_permutation = NULL;
1858                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1859                         for (i = 0;i < limit;i++)
1860                         {
1861                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1862                                 {
1863                                         GL_Backend_FreeProgram(p->program);
1864                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1865                                 }
1866                         }
1867                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1868                 }
1869                 break;
1870         case RENDERPATH_GL11:
1871         case RENDERPATH_GL13:
1872         case RENDERPATH_GLES1:
1873                 break;
1874         case RENDERPATH_SOFT:
1875                 break;
1876         }
1877 }
1878
1879 static void R_GLSL_DumpShader_f(void)
1880 {
1881         int i;
1882         qfile_t *file;
1883
1884         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1885         if (file)
1886         {
1887                 FS_Print(file, "/* The engine may define the following macros:\n");
1888                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1889                 for (i = 0;i < SHADERMODE_COUNT;i++)
1890                         FS_Print(file, glslshadermodeinfo[i].pretext);
1891                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1892                         FS_Print(file, shaderpermutationinfo[i].pretext);
1893                 FS_Print(file, "*/\n");
1894                 FS_Print(file, builtinshaderstring);
1895                 FS_Close(file);
1896                 Con_Printf("glsl/default.glsl written\n");
1897         }
1898         else
1899                 Con_Printf("failed to write to glsl/default.glsl\n");
1900
1901         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1902         if (file)
1903         {
1904                 FS_Print(file, "/* The engine may define the following macros:\n");
1905                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1906                 for (i = 0;i < SHADERMODE_COUNT;i++)
1907                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1908                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1909                         FS_Print(file, shaderpermutationinfo[i].pretext);
1910                 FS_Print(file, "*/\n");
1911                 FS_Print(file, builtinhlslshaderstring);
1912                 FS_Close(file);
1913                 Con_Printf("hlsl/default.hlsl written\n");
1914         }
1915         else
1916                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1917 }
1918
1919 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1920 {
1921         unsigned int permutation = 0;
1922         if (r_trippy.integer && !notrippy)
1923                 permutation |= SHADERPERMUTATION_TRIPPY;
1924         permutation |= SHADERPERMUTATION_VIEWTINT;
1925         if (first)
1926                 permutation |= SHADERPERMUTATION_DIFFUSE;
1927         if (second)
1928                 permutation |= SHADERPERMUTATION_SPECULAR;
1929         if (texturemode == GL_MODULATE)
1930                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1931         else if (texturemode == GL_ADD)
1932                 permutation |= SHADERPERMUTATION_GLOW;
1933         else if (texturemode == GL_DECAL)
1934                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1935         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1936                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1937         if (suppresstexalpha)
1938                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1939         if (!second)
1940                 texturemode = GL_MODULATE;
1941         if (vid.allowalphatocoverage)
1942                 GL_AlphaToCoverage(false);
1943         switch (vid.renderpath)
1944         {
1945         case RENDERPATH_D3D9:
1946 #ifdef SUPPORTD3D
1947                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1948                 R_Mesh_TexBind(GL20TU_FIRST , first );
1949                 R_Mesh_TexBind(GL20TU_SECOND, second);
1950                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1951                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1952 #endif
1953                 break;
1954         case RENDERPATH_D3D10:
1955                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1956                 break;
1957         case RENDERPATH_D3D11:
1958                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1959                 break;
1960         case RENDERPATH_GL20:
1961         case RENDERPATH_GLES2:
1962                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1963                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1964                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1965                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1966                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1967                 break;
1968         case RENDERPATH_GL13:
1969         case RENDERPATH_GLES1:
1970                 R_Mesh_TexBind(0, first );
1971                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1972                 R_Mesh_TexBind(1, second);
1973                 if (second)
1974                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1975                 break;
1976         case RENDERPATH_GL11:
1977                 R_Mesh_TexBind(0, first );
1978                 break;
1979         case RENDERPATH_SOFT:
1980                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1981                 R_Mesh_TexBind(GL20TU_FIRST , first );
1982                 R_Mesh_TexBind(GL20TU_SECOND, second);
1983                 break;
1984         }
1985 }
1986
1987 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1988 {
1989         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1990 }
1991
1992 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1993 {
1994         unsigned int permutation = 0;
1995         if (r_trippy.integer && !notrippy)
1996                 permutation |= SHADERPERMUTATION_TRIPPY;
1997         if (depthrgb)
1998                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1999         if (vid.allowalphatocoverage)
2000                 GL_AlphaToCoverage(false);
2001         switch (vid.renderpath)
2002         {
2003         case RENDERPATH_D3D9:
2004 #ifdef SUPPORTD3D
2005                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2006 #endif
2007                 break;
2008         case RENDERPATH_D3D10:
2009                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2010                 break;
2011         case RENDERPATH_D3D11:
2012                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2013                 break;
2014         case RENDERPATH_GL20:
2015         case RENDERPATH_GLES2:
2016                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2017                 break;
2018         case RENDERPATH_GL13:
2019         case RENDERPATH_GLES1:
2020                 R_Mesh_TexBind(0, 0);
2021                 R_Mesh_TexBind(1, 0);
2022                 break;
2023         case RENDERPATH_GL11:
2024                 R_Mesh_TexBind(0, 0);
2025                 break;
2026         case RENDERPATH_SOFT:
2027                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2028                 break;
2029         }
2030 }
2031
2032 void R_SetupShader_ShowDepth(qboolean notrippy)
2033 {
2034         int permutation = 0;
2035         if (r_trippy.integer && !notrippy)
2036                 permutation |= SHADERPERMUTATION_TRIPPY;
2037         if (vid.allowalphatocoverage)
2038                 GL_AlphaToCoverage(false);
2039         switch (vid.renderpath)
2040         {
2041         case RENDERPATH_D3D9:
2042 #ifdef SUPPORTHLSL
2043                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2044 #endif
2045                 break;
2046         case RENDERPATH_D3D10:
2047                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2048                 break;
2049         case RENDERPATH_D3D11:
2050                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2051                 break;
2052         case RENDERPATH_GL20:
2053         case RENDERPATH_GLES2:
2054                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2055                 break;
2056         case RENDERPATH_GL13:
2057         case RENDERPATH_GLES1:
2058                 break;
2059         case RENDERPATH_GL11:
2060                 break;
2061         case RENDERPATH_SOFT:
2062                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2063                 break;
2064         }
2065 }
2066
2067 extern qboolean r_shadow_usingdeferredprepass;
2068 extern rtexture_t *r_shadow_attenuationgradienttexture;
2069 extern rtexture_t *r_shadow_attenuation2dtexture;
2070 extern rtexture_t *r_shadow_attenuation3dtexture;
2071 extern qboolean r_shadow_usingshadowmap2d;
2072 extern qboolean r_shadow_usingshadowmaportho;
2073 extern float r_shadow_shadowmap_texturescale[2];
2074 extern float r_shadow_shadowmap_parameters[4];
2075 extern qboolean r_shadow_shadowmapvsdct;
2076 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2077 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2078 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2079 extern matrix4x4_t r_shadow_shadowmapmatrix;
2080 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2081 extern int r_shadow_prepass_width;
2082 extern int r_shadow_prepass_height;
2083 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2084 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2085 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2086 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2087
2088 #define BLENDFUNC_ALLOWS_COLORMOD      1
2089 #define BLENDFUNC_ALLOWS_FOG           2
2090 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2091 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2092 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2093 static int R_BlendFuncFlags(int src, int dst)
2094 {
2095         int r = 0;
2096
2097         // a blendfunc allows colormod if:
2098         // a) it can never keep the destination pixel invariant, or
2099         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2100         // this is to prevent unintended side effects from colormod
2101
2102         // a blendfunc allows fog if:
2103         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2104         // this is to prevent unintended side effects from fog
2105
2106         // these checks are the output of fogeval.pl
2107
2108         r |= BLENDFUNC_ALLOWS_COLORMOD;
2109         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2110         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2111         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2112         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2113         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2114         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2115         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2116         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2117         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2118         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2119         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2120         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2121         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2122         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2123         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2124         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2125         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2126         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2127         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2128         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2129         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2130
2131         return r;
2132 }
2133
2134 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)
2135 {
2136         // select a permutation of the lighting shader appropriate to this
2137         // combination of texture, entity, light source, and fogging, only use the
2138         // minimum features necessary to avoid wasting rendering time in the
2139         // fragment shader on features that are not being used
2140         unsigned int permutation = 0;
2141         unsigned int mode = 0;
2142         int blendfuncflags;
2143         static float dummy_colormod[3] = {1, 1, 1};
2144         float *colormod = rsurface.colormod;
2145         float m16f[16];
2146         matrix4x4_t tempmatrix;
2147         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2148         if (r_trippy.integer && !notrippy)
2149                 permutation |= SHADERPERMUTATION_TRIPPY;
2150         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2151                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2152         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2153                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2154         if (rsurfacepass == RSURFPASS_BACKGROUND)
2155         {
2156                 // distorted background
2157                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2158                 {
2159                         mode = SHADERMODE_WATER;
2160                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2161                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2162                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2163                         {
2164                                 // this is the right thing to do for wateralpha
2165                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2166                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2167                         }
2168                         else
2169                         {
2170                                 // this is the right thing to do for entity alpha
2171                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2172                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2173                         }
2174                 }
2175                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2176                 {
2177                         mode = SHADERMODE_REFRACTION;
2178                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2179                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2180                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2181                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2182                 }
2183                 else
2184                 {
2185                         mode = SHADERMODE_GENERIC;
2186                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2187                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2188                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2189                 }
2190                 if (vid.allowalphatocoverage)
2191                         GL_AlphaToCoverage(false);
2192         }
2193         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2194         {
2195                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2196                 {
2197                         switch(rsurface.texture->offsetmapping)
2198                         {
2199                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2200                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202                         case OFFSETMAPPING_OFF: break;
2203                         }
2204                 }
2205                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2206                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2207                 // normalmap (deferred prepass), may use alpha test on diffuse
2208                 mode = SHADERMODE_DEFERREDGEOMETRY;
2209                 GL_BlendFunc(GL_ONE, GL_ZERO);
2210                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2211                 if (vid.allowalphatocoverage)
2212                         GL_AlphaToCoverage(false);
2213         }
2214         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2215         {
2216                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2217                 {
2218                         switch(rsurface.texture->offsetmapping)
2219                         {
2220                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2221                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2222                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2223                         case OFFSETMAPPING_OFF: break;
2224                         }
2225                 }
2226                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2227                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2228                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2229                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2230                 // light source
2231                 mode = SHADERMODE_LIGHTSOURCE;
2232                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2233                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2234                 if (diffusescale > 0)
2235                         permutation |= SHADERPERMUTATION_DIFFUSE;
2236                 if (specularscale > 0)
2237                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2238                 if (r_refdef.fogenabled)
2239                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2240                 if (rsurface.texture->colormapping)
2241                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2242                 if (r_shadow_usingshadowmap2d)
2243                 {
2244                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2245                         if(r_shadow_shadowmapvsdct)
2246                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2247
2248                         if (r_shadow_shadowmap2ddepthbuffer)
2249                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2250                 }
2251                 if (rsurface.texture->reflectmasktexture)
2252                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2253                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2254                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2255                 if (vid.allowalphatocoverage)
2256                         GL_AlphaToCoverage(false);
2257         }
2258         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2259         {
2260                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2261                 {
2262                         switch(rsurface.texture->offsetmapping)
2263                         {
2264                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2265                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2266                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2267                         case OFFSETMAPPING_OFF: break;
2268                         }
2269                 }
2270                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2271                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2272                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2273                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2274                 // unshaded geometry (fullbright or ambient model lighting)
2275                 mode = SHADERMODE_FLATCOLOR;
2276                 ambientscale = diffusescale = specularscale = 0;
2277                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2278                         permutation |= SHADERPERMUTATION_GLOW;
2279                 if (r_refdef.fogenabled)
2280                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2281                 if (rsurface.texture->colormapping)
2282                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2283                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2284                 {
2285                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2286                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2287
2288                         if (r_shadow_shadowmap2ddepthbuffer)
2289                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2290                 }
2291                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2292                         permutation |= SHADERPERMUTATION_REFLECTION;
2293                 if (rsurface.texture->reflectmasktexture)
2294                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2295                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2296                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2297                 // when using alphatocoverage, we don't need alphakill
2298                 if (vid.allowalphatocoverage)
2299                 {
2300                         if (r_transparent_alphatocoverage.integer)
2301                         {
2302                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2303                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2304                         }
2305                         else
2306                                 GL_AlphaToCoverage(false);
2307                 }
2308         }
2309         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2310         {
2311                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2312                 {
2313                         switch(rsurface.texture->offsetmapping)
2314                         {
2315                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2316                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2317                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2318                         case OFFSETMAPPING_OFF: break;
2319                         }
2320                 }
2321                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2322                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2323                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2324                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2325                 // directional model lighting
2326                 mode = SHADERMODE_LIGHTDIRECTION;
2327                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2328                         permutation |= SHADERPERMUTATION_GLOW;
2329                 permutation |= SHADERPERMUTATION_DIFFUSE;
2330                 if (specularscale > 0)
2331                         permutation |= SHADERPERMUTATION_SPECULAR;
2332                 if (r_refdef.fogenabled)
2333                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2334                 if (rsurface.texture->colormapping)
2335                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2336                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2337                 {
2338                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2339                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2340
2341                         if (r_shadow_shadowmap2ddepthbuffer)
2342                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2343                 }
2344                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2345                         permutation |= SHADERPERMUTATION_REFLECTION;
2346                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2347                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2348                 if (rsurface.texture->reflectmasktexture)
2349                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2350                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2351                 {
2352                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2353                         if (r_shadow_bouncegriddirectional)
2354                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2355                 }
2356                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2357                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2358                 // when using alphatocoverage, we don't need alphakill
2359                 if (vid.allowalphatocoverage)
2360                 {
2361                         if (r_transparent_alphatocoverage.integer)
2362                         {
2363                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2364                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2365                         }
2366                         else
2367                                 GL_AlphaToCoverage(false);
2368                 }
2369         }
2370         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2371         {
2372                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2373                 {
2374                         switch(rsurface.texture->offsetmapping)
2375                         {
2376                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2377                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2378                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2379                         case OFFSETMAPPING_OFF: break;
2380                         }
2381                 }
2382                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2383                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2384                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2385                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2386                 // ambient model lighting
2387                 mode = SHADERMODE_LIGHTDIRECTION;
2388                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2389                         permutation |= SHADERPERMUTATION_GLOW;
2390                 if (r_refdef.fogenabled)
2391                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2392                 if (rsurface.texture->colormapping)
2393                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2394                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2395                 {
2396                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2397                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2398
2399                         if (r_shadow_shadowmap2ddepthbuffer)
2400                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2401                 }
2402                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2403                         permutation |= SHADERPERMUTATION_REFLECTION;
2404                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2405                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2406                 if (rsurface.texture->reflectmasktexture)
2407                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2408                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2409                 {
2410                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2411                         if (r_shadow_bouncegriddirectional)
2412                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2413                 }
2414                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2416                 // when using alphatocoverage, we don't need alphakill
2417                 if (vid.allowalphatocoverage)
2418                 {
2419                         if (r_transparent_alphatocoverage.integer)
2420                         {
2421                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2422                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2423                         }
2424                         else
2425                                 GL_AlphaToCoverage(false);
2426                 }
2427         }
2428         else
2429         {
2430                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2431                 {
2432                         switch(rsurface.texture->offsetmapping)
2433                         {
2434                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2435                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2436                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2437                         case OFFSETMAPPING_OFF: break;
2438                         }
2439                 }
2440                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2441                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2442                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2443                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2444                 // lightmapped wall
2445                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2446                         permutation |= SHADERPERMUTATION_GLOW;
2447                 if (r_refdef.fogenabled)
2448                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2449                 if (rsurface.texture->colormapping)
2450                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2451                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2452                 {
2453                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2454                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2455
2456                         if (r_shadow_shadowmap2ddepthbuffer)
2457                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2458                 }
2459                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2460                         permutation |= SHADERPERMUTATION_REFLECTION;
2461                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2462                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2463                 if (rsurface.texture->reflectmasktexture)
2464                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2465                 if (FAKELIGHT_ENABLED)
2466                 {
2467                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2468                         mode = SHADERMODE_FAKELIGHT;
2469                         permutation |= SHADERPERMUTATION_DIFFUSE;
2470                         if (specularscale > 0)
2471                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2472                 }
2473                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2474                 {
2475                         // deluxemapping (light direction texture)
2476                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2477                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2478                         else
2479                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2480                         permutation |= SHADERPERMUTATION_DIFFUSE;
2481                         if (specularscale > 0)
2482                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2483                 }
2484                 else if (r_glsl_deluxemapping.integer >= 2)
2485                 {
2486                         // fake deluxemapping (uniform light direction in tangentspace)
2487                         if (rsurface.uselightmaptexture)
2488                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2489                         else
2490                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2491                         permutation |= SHADERPERMUTATION_DIFFUSE;
2492                         if (specularscale > 0)
2493                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2494                 }
2495                 else if (rsurface.uselightmaptexture)
2496                 {
2497                         // ordinary lightmapping (q1bsp, q3bsp)
2498                         mode = SHADERMODE_LIGHTMAP;
2499                 }
2500                 else
2501                 {
2502                         // ordinary vertex coloring (q3bsp)
2503                         mode = SHADERMODE_VERTEXCOLOR;
2504                 }
2505                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2506                 {
2507                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2508                         if (r_shadow_bouncegriddirectional)
2509                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2510                 }
2511                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2512                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2513                 // when using alphatocoverage, we don't need alphakill
2514                 if (vid.allowalphatocoverage)
2515                 {
2516                         if (r_transparent_alphatocoverage.integer)
2517                         {
2518                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2519                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2520                         }
2521                         else
2522                                 GL_AlphaToCoverage(false);
2523                 }
2524         }
2525         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2526                 colormod = dummy_colormod;
2527         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2528                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2529         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2530                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2531         switch(vid.renderpath)
2532         {
2533         case RENDERPATH_D3D9:
2534 #ifdef SUPPORTD3D
2535                 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);
2536                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2537                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2538                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2539                 if (mode == SHADERMODE_LIGHTSOURCE)
2540                 {
2541                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2542                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2543                 }
2544                 else
2545                 {
2546                         if (mode == SHADERMODE_LIGHTDIRECTION)
2547                         {
2548                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2549                         }
2550                 }
2551                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2552                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2553                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2554                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2555                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2556
2557                 if (mode == SHADERMODE_LIGHTSOURCE)
2558                 {
2559                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2560                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2561                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2562                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2563                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2564
2565                         // additive passes are only darkened by fog, not tinted
2566                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2567                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2568                 }
2569                 else
2570                 {
2571                         if (mode == SHADERMODE_FLATCOLOR)
2572                         {
2573                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2574                         }
2575                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2576                         {
2577                                 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]);
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2579                                 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);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2581                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2582                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2583                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2584                         }
2585                         else
2586                         {
2587                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2588                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2589                                 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);
2590                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2591                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2592                         }
2593                         // additive passes are only darkened by fog, not tinted
2594                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2595                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2596                         else
2597                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2598                         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);
2599                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2600                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2601                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2602                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2603                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2604                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2605                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2606                         if (mode == SHADERMODE_WATER)
2607                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2608                 }
2609                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2610                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2611                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2612                 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));
2613                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2614                 if (rsurface.texture->pantstexture)
2615                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2616                 else
2617                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2618                 if (rsurface.texture->shirttexture)
2619                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2620                 else
2621                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2622                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2623                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2624                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2625                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2626                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2627                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2628                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2629                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2630                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2631                         );
2632                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2633                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2634                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2635                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2636
2637                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2638                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2639                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2640                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2641                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2642                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2643                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2644                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2645                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2646                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2647                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2648                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2649                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2650                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2651                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2652                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2653                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2654                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2655                 {
2656                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2657                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2658                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2659                 }
2660                 else
2661                 {
2662                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2663                 }
2664 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2665                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2666                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2667                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2668                 {
2669                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2670                         if (rsurface.rtlight)
2671                         {
2672                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2673                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2674                         }
2675                 }
2676 #endif
2677                 break;
2678         case RENDERPATH_D3D10:
2679                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2680                 break;
2681         case RENDERPATH_D3D11:
2682                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2683                 break;
2684         case RENDERPATH_GL20:
2685         case RENDERPATH_GLES2:
2686                 if (!vid.useinterleavedarrays)
2687                 {
2688                         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);
2689                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2690                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2691                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2692                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2693                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2694                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2695                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2696                 }
2697                 else
2698                 {
2699                         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);
2700                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2701                 }
2702                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2703                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2704                 if (mode == SHADERMODE_LIGHTSOURCE)
2705                 {
2706                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2707                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2708                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2709                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2710                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2711                         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);
2712         
2713                         // additive passes are only darkened by fog, not tinted
2714                         if (r_glsl_permutation->loc_FogColor >= 0)
2715                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2716                         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);
2717                 }
2718                 else
2719                 {
2720                         if (mode == SHADERMODE_FLATCOLOR)
2721                         {
2722                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2723                         }
2724                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2725                         {
2726                                 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]);
2727                                 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]);
2728                                 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);
2729                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2730                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2731                                 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]);
2732                                 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]);
2733                         }
2734                         else
2735                         {
2736                                 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]);
2737                                 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]);
2738                                 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);
2739                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2740                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2741                         }
2742                         // additive passes are only darkened by fog, not tinted
2743                         if (r_glsl_permutation->loc_FogColor >= 0)
2744                         {
2745                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2746                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2747                                 else
2748                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2749                         }
2750                         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);
2751                         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]);
2752                         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]);
2753                         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]);
2754                         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]);
2755                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2756                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2757                         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);
2758                         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]);
2759                 }
2760                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2761                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2762                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2763                 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]);
2764                 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]);
2765
2766                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2767                 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));
2768                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2769                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2770                 {
2771                         if (rsurface.texture->pantstexture)
2772                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2773                         else
2774                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2775                 }
2776                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2777                 {
2778                         if (rsurface.texture->shirttexture)
2779                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2780                         else
2781                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2782                 }
2783                 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]);
2784                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2785                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2786                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2787                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2788                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2789                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2790                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2791                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2792                         );
2793                 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);
2794                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2795                 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]);
2796                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2797                 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);}
2798                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2799
2800                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2801                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2802                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2803                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2804                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2805                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2806                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2807                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2808                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2809                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2810                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2811                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2812                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2813                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2814                 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);
2815                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2816                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2817                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2818                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2819                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2820                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2821                 {
2822                         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);
2823                         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);
2824                         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);
2825                 }
2826                 else
2827                 {
2828                         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);
2829                 }
2830                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2831                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2832                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2833                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2834                 {
2835                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2836                         if (rsurface.rtlight)
2837                         {
2838                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2839                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2840                         }
2841                 }
2842                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2843                 CHECKGLERROR
2844                 break;
2845         case RENDERPATH_GL11:
2846         case RENDERPATH_GL13:
2847         case RENDERPATH_GLES1:
2848                 break;
2849         case RENDERPATH_SOFT:
2850                 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);
2851                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2852                 R_SetupShader_SetPermutationSoft(mode, permutation);
2853                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2854                 if (mode == SHADERMODE_LIGHTSOURCE)
2855                 {
2856                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2857                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2858                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2859                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2860                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2861                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2862         
2863                         // additive passes are only darkened by fog, not tinted
2864                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2865                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2866                 }
2867                 else
2868                 {
2869                         if (mode == SHADERMODE_FLATCOLOR)
2870                         {
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2872                         }
2873                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2874                         {
2875                                 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]);
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2880                                 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]);
2881                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2882                         }
2883                         else
2884                         {
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2886                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2887                                 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);
2888                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2889                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2890                         }
2891                         // additive passes are only darkened by fog, not tinted
2892                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2893                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2894                         else
2895                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2896                         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);
2897                         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]);
2898                         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]);
2899                         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]);
2900                         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]);
2901                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2902                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2903                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2904                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2905                 }
2906                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2907                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2908                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2909                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2910                 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]);
2911
2912                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2913                 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));
2914                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2915                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2916                 {
2917                         if (rsurface.texture->pantstexture)
2918                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2919                         else
2920                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2921                 }
2922                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2923                 {
2924                         if (rsurface.texture->shirttexture)
2925                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2926                         else
2927                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2928                 }
2929                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2930                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2931                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2932                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2933                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2934                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2935                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2936                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2937                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2938                         );
2939                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2940                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2941                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2942                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2943
2944                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2945                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2946                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2947                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2948                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2949                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2950                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2951                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2952                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2953                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2954                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2955                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2956                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2957                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2958                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2959                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2960                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2961                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2962                 {
2963                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2964                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2965                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2966                 }
2967                 else
2968                 {
2969                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2970                 }
2971 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2972                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2973                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2974                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2975                 {
2976                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2977                         if (rsurface.rtlight)
2978                         {
2979                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2980                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2981                         }
2982                 }
2983                 break;
2984         }
2985 }
2986
2987 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2988 {
2989         // select a permutation of the lighting shader appropriate to this
2990         // combination of texture, entity, light source, and fogging, only use the
2991         // minimum features necessary to avoid wasting rendering time in the
2992         // fragment shader on features that are not being used
2993         unsigned int permutation = 0;
2994         unsigned int mode = 0;
2995         const float *lightcolorbase = rtlight->currentcolor;
2996         float ambientscale = rtlight->ambientscale;
2997         float diffusescale = rtlight->diffusescale;
2998         float specularscale = rtlight->specularscale;
2999         // this is the location of the light in view space
3000         vec3_t viewlightorigin;
3001         // this transforms from view space (camera) to light space (cubemap)
3002         matrix4x4_t viewtolight;
3003         matrix4x4_t lighttoview;
3004         float viewtolight16f[16];
3005         // light source
3006         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3007         if (rtlight->currentcubemap != r_texture_whitecube)
3008                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3009         if (diffusescale > 0)
3010                 permutation |= SHADERPERMUTATION_DIFFUSE;
3011         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3012                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3013         if (r_shadow_usingshadowmap2d)
3014         {
3015                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3016                 if (r_shadow_shadowmapvsdct)
3017                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3018
3019                 if (r_shadow_shadowmap2ddepthbuffer)
3020                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3021         }
3022         if (vid.allowalphatocoverage)
3023                 GL_AlphaToCoverage(false);
3024         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3025         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3026         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3027         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3028         switch(vid.renderpath)
3029         {
3030         case RENDERPATH_D3D9:
3031 #ifdef SUPPORTD3D
3032                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3033                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3034                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3035                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3036                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3037                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3038                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3039                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3040                 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);
3041                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3042                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3043
3044                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3045                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3046                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3047                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3048                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3049 #endif
3050                 break;
3051         case RENDERPATH_D3D10:
3052                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3053                 break;
3054         case RENDERPATH_D3D11:
3055                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3056                 break;
3057         case RENDERPATH_GL20:
3058         case RENDERPATH_GLES2:
3059                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3060                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3061                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3062                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3063                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3064                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3065                 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]);
3066                 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]);
3067                 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);
3068                 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]);
3069                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3070
3071                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3072                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3073                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3074                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3075                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3076                 break;
3077         case RENDERPATH_GL11:
3078         case RENDERPATH_GL13:
3079         case RENDERPATH_GLES1:
3080                 break;
3081         case RENDERPATH_SOFT:
3082                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3083                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3084                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3085                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3086                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3087                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3088                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3089                 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]);
3090                 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);
3091                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3092                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3093
3094                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3095                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3096                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3097                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3098                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3099                 break;
3100         }
3101 }
3102
3103 #define SKINFRAME_HASH 1024
3104
3105 typedef struct
3106 {
3107         int loadsequence; // incremented each level change
3108         memexpandablearray_t array;
3109         skinframe_t *hash[SKINFRAME_HASH];
3110 }
3111 r_skinframe_t;
3112 r_skinframe_t r_skinframe;
3113
3114 void R_SkinFrame_PrepareForPurge(void)
3115 {
3116         r_skinframe.loadsequence++;
3117         // wrap it without hitting zero
3118         if (r_skinframe.loadsequence >= 200)
3119                 r_skinframe.loadsequence = 1;
3120 }
3121
3122 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3123 {
3124         if (!skinframe)
3125                 return;
3126         // mark the skinframe as used for the purging code
3127         skinframe->loadsequence = r_skinframe.loadsequence;
3128 }
3129
3130 void R_SkinFrame_Purge(void)
3131 {
3132         int i;
3133         skinframe_t *s;
3134         for (i = 0;i < SKINFRAME_HASH;i++)
3135         {
3136                 for (s = r_skinframe.hash[i];s;s = s->next)
3137                 {
3138                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3139                         {
3140                                 if (s->merged == s->base)
3141                                         s->merged = NULL;
3142                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3143                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3144                                 R_PurgeTexture(s->merged);s->merged = NULL;
3145                                 R_PurgeTexture(s->base  );s->base   = NULL;
3146                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3147                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3148                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3149                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3150                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3151                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3152                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3153                                 s->loadsequence = 0;
3154                         }
3155                 }
3156         }
3157 }
3158
3159 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3160         skinframe_t *item;
3161         char basename[MAX_QPATH];
3162
3163         Image_StripImageExtension(name, basename, sizeof(basename));
3164
3165         if( last == NULL ) {
3166                 int hashindex;
3167                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3168                 item = r_skinframe.hash[hashindex];
3169         } else {
3170                 item = last->next;
3171         }
3172
3173         // linearly search through the hash bucket
3174         for( ; item ; item = item->next ) {
3175                 if( !strcmp( item->basename, basename ) ) {
3176                         return item;
3177                 }
3178         }
3179         return NULL;
3180 }
3181
3182 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3183 {
3184         skinframe_t *item;
3185         int hashindex;
3186         char basename[MAX_QPATH];
3187
3188         Image_StripImageExtension(name, basename, sizeof(basename));
3189
3190         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3191         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3192                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3193                         break;
3194
3195         if (!item) {
3196                 rtexture_t *dyntexture;
3197                 // check whether its a dynamic texture
3198                 dyntexture = CL_GetDynTexture( basename );
3199                 if (!add && !dyntexture)
3200                         return NULL;
3201                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3202                 memset(item, 0, sizeof(*item));
3203                 strlcpy(item->basename, basename, sizeof(item->basename));
3204                 item->base = dyntexture; // either NULL or dyntexture handle
3205                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3206                 item->comparewidth = comparewidth;
3207                 item->compareheight = compareheight;
3208                 item->comparecrc = comparecrc;
3209                 item->next = r_skinframe.hash[hashindex];
3210                 r_skinframe.hash[hashindex] = item;
3211         }
3212         else if (textureflags & TEXF_FORCE_RELOAD)
3213         {
3214                 rtexture_t *dyntexture;
3215                 // check whether its a dynamic texture
3216                 dyntexture = CL_GetDynTexture( basename );
3217                 if (!add && !dyntexture)
3218                         return NULL;
3219                 if (item->merged == item->base)
3220                         item->merged = NULL;
3221                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3222                 R_PurgeTexture(item->stain );item->stain  = NULL;
3223                 R_PurgeTexture(item->merged);item->merged = NULL;
3224                 R_PurgeTexture(item->base  );item->base   = NULL;
3225                 R_PurgeTexture(item->pants );item->pants  = NULL;
3226                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3227                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3228                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3229                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3230                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3231         R_PurgeTexture(item->reflect);item->reflect = NULL;
3232                 item->loadsequence = 0;
3233         }
3234         else if( item->base == NULL )
3235         {
3236                 rtexture_t *dyntexture;
3237                 // check whether its a dynamic texture
3238                 // 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]
3239                 dyntexture = CL_GetDynTexture( basename );
3240                 item->base = dyntexture; // either NULL or dyntexture handle
3241         }
3242
3243         R_SkinFrame_MarkUsed(item);
3244         return item;
3245 }
3246
3247 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3248         { \
3249                 unsigned long long avgcolor[5], wsum; \
3250                 int pix, comp, w; \
3251                 avgcolor[0] = 0; \
3252                 avgcolor[1] = 0; \
3253                 avgcolor[2] = 0; \
3254                 avgcolor[3] = 0; \
3255                 avgcolor[4] = 0; \
3256                 wsum = 0; \
3257                 for(pix = 0; pix < cnt; ++pix) \
3258                 { \
3259                         w = 0; \
3260                         for(comp = 0; comp < 3; ++comp) \
3261                                 w += getpixel; \
3262                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3263                         { \
3264                                 ++wsum; \
3265                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3266                                 w = getpixel; \
3267                                 for(comp = 0; comp < 3; ++comp) \
3268                                         avgcolor[comp] += getpixel * w; \
3269                                 avgcolor[3] += w; \
3270                         } \
3271                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3272                         avgcolor[4] += getpixel; \
3273                 } \
3274                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3275                         avgcolor[3] = 1; \
3276                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3277                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3278                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3279                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3280         }
3281
3282 extern cvar_t gl_picmip;
3283 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3284 {
3285         int j;
3286         unsigned char *pixels;
3287         unsigned char *bumppixels;
3288         unsigned char *basepixels = NULL;
3289         int basepixels_width = 0;
3290         int basepixels_height = 0;
3291         skinframe_t *skinframe;
3292         rtexture_t *ddsbase = NULL;
3293         qboolean ddshasalpha = false;
3294         float ddsavgcolor[4];
3295         char basename[MAX_QPATH];
3296         int miplevel = R_PicmipForFlags(textureflags);
3297         int savemiplevel = miplevel;
3298         int mymiplevel;
3299         char vabuf[1024];
3300
3301         if (cls.state == ca_dedicated)
3302                 return NULL;
3303
3304         // return an existing skinframe if already loaded
3305         // if loading of the first image fails, don't make a new skinframe as it
3306         // would cause all future lookups of this to be missing
3307         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3308         if (skinframe && skinframe->base)
3309                 return skinframe;
3310
3311         Image_StripImageExtension(name, basename, sizeof(basename));
3312
3313         // check for DDS texture file first
3314         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3315         {
3316                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3317                 if (basepixels == NULL)
3318                         return NULL;
3319         }
3320
3321         // FIXME handle miplevel
3322
3323         if (developer_loading.integer)
3324                 Con_Printf("loading skin \"%s\"\n", name);
3325
3326         // we've got some pixels to store, so really allocate this new texture now
3327         if (!skinframe)
3328                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3329         textureflags &= ~TEXF_FORCE_RELOAD;
3330         skinframe->stain = NULL;
3331         skinframe->merged = NULL;
3332         skinframe->base = NULL;
3333         skinframe->pants = NULL;
3334         skinframe->shirt = NULL;
3335         skinframe->nmap = NULL;
3336         skinframe->gloss = NULL;
3337         skinframe->glow = NULL;
3338         skinframe->fog = NULL;
3339         skinframe->reflect = NULL;
3340         skinframe->hasalpha = false;
3341
3342         if (ddsbase)
3343         {
3344                 skinframe->base = ddsbase;
3345                 skinframe->hasalpha = ddshasalpha;
3346                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3347                 if (r_loadfog && skinframe->hasalpha)
3348                         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);
3349                 //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]);
3350         }
3351         else
3352         {
3353                 basepixels_width = image_width;
3354                 basepixels_height = image_height;
3355                 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);
3356                 if (textureflags & TEXF_ALPHA)
3357                 {
3358                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3359                         {
3360                                 if (basepixels[j] < 255)
3361                                 {
3362                                         skinframe->hasalpha = true;
3363                                         break;
3364                                 }
3365                         }
3366                         if (r_loadfog && skinframe->hasalpha)
3367                         {
3368                                 // has transparent pixels
3369                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3370                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3371                                 {
3372                                         pixels[j+0] = 255;
3373                                         pixels[j+1] = 255;
3374                                         pixels[j+2] = 255;
3375                                         pixels[j+3] = basepixels[j+3];
3376                                 }
3377                                 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);
3378                                 Mem_Free(pixels);
3379                         }
3380                 }
3381                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3382 #ifndef USE_GLES2
3383                 //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]);
3384                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3385                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3386                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3387                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3388 #endif
3389         }
3390
3391         if (r_loaddds)
3392         {
3393                 mymiplevel = savemiplevel;
3394                 if (r_loadnormalmap)
3395                         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);
3396                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3397                 if (r_loadgloss)
3398                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3399                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3400                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3401                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3402         }
3403
3404         // _norm is the name used by tenebrae and has been adopted as standard
3405         if (r_loadnormalmap && skinframe->nmap == NULL)
3406         {
3407                 mymiplevel = savemiplevel;
3408                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3409                 {
3410                         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);
3411                         Mem_Free(pixels);
3412                         pixels = NULL;
3413                 }
3414                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3415                 {
3416                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3417                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3418                         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);
3419                         Mem_Free(pixels);
3420                         Mem_Free(bumppixels);
3421                 }
3422                 else if (r_shadow_bumpscale_basetexture.value > 0)
3423                 {
3424                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3425                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3426                         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);
3427                         Mem_Free(pixels);
3428                 }
3429 #ifndef USE_GLES2
3430                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3431                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3432 #endif
3433         }
3434
3435         // _luma is supported only for tenebrae compatibility
3436         // _glow is the preferred name
3437         mymiplevel = savemiplevel;
3438         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))))
3439         {
3440                 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);
3441 #ifndef USE_GLES2
3442                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3443                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3444 #endif
3445                 Mem_Free(pixels);pixels = NULL;
3446         }
3447
3448         mymiplevel = savemiplevel;
3449         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3450         {
3451                 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);
3452 #ifndef USE_GLES2
3453                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3454                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3455 #endif
3456                 Mem_Free(pixels);
3457                 pixels = NULL;
3458         }
3459
3460         mymiplevel = savemiplevel;
3461         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3462         {
3463                 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);
3464 #ifndef USE_GLES2
3465                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3466                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3467 #endif
3468                 Mem_Free(pixels);
3469                 pixels = NULL;
3470         }
3471
3472         mymiplevel = savemiplevel;
3473         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3474         {
3475                 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);
3476 #ifndef USE_GLES2
3477                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3478                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3479 #endif
3480                 Mem_Free(pixels);
3481                 pixels = NULL;
3482         }
3483
3484         mymiplevel = savemiplevel;
3485         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3486         {
3487                 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);
3488 #ifndef USE_GLES2
3489                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3490                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3491 #endif
3492                 Mem_Free(pixels);
3493                 pixels = NULL;
3494         }
3495
3496         if (basepixels)
3497                 Mem_Free(basepixels);
3498
3499         return skinframe;
3500 }
3501
3502 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3503 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3504 {
3505         int i;
3506         unsigned char *temp1, *temp2;
3507         skinframe_t *skinframe;
3508         char vabuf[1024];
3509
3510         if (cls.state == ca_dedicated)
3511                 return NULL;
3512
3513         // if already loaded just return it, otherwise make a new skinframe
3514         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3515         if (skinframe->base)
3516                 return skinframe;
3517         textureflags &= ~TEXF_FORCE_RELOAD;
3518
3519         skinframe->stain = NULL;
3520         skinframe->merged = NULL;
3521         skinframe->base = NULL;
3522         skinframe->pants = NULL;
3523         skinframe->shirt = NULL;
3524         skinframe->nmap = NULL;
3525         skinframe->gloss = NULL;
3526         skinframe->glow = NULL;
3527         skinframe->fog = NULL;
3528         skinframe->reflect = NULL;
3529         skinframe->hasalpha = false;
3530
3531         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3532         if (!skindata)
3533                 return NULL;
3534
3535         if (developer_loading.integer)
3536                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3537
3538         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3539         {
3540                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3541                 temp2 = temp1 + width * height * 4;
3542                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3543                 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);
3544                 Mem_Free(temp1);
3545         }
3546         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3547         if (textureflags & TEXF_ALPHA)
3548         {
3549                 for (i = 3;i < width * height * 4;i += 4)
3550                 {
3551                         if (skindata[i] < 255)
3552                         {
3553                                 skinframe->hasalpha = true;
3554                                 break;
3555                         }
3556                 }
3557                 if (r_loadfog && skinframe->hasalpha)
3558                 {
3559                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3560                         memcpy(fogpixels, skindata, width * height * 4);
3561                         for (i = 0;i < width * height * 4;i += 4)
3562                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3563                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3564                         Mem_Free(fogpixels);
3565                 }
3566         }
3567
3568         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3569         //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]);
3570
3571         return skinframe;
3572 }
3573
3574 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3575 {
3576         int i;
3577         int featuresmask;
3578         skinframe_t *skinframe;
3579
3580         if (cls.state == ca_dedicated)
3581                 return NULL;
3582
3583         // if already loaded just return it, otherwise make a new skinframe
3584         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3585         if (skinframe->base)
3586                 return skinframe;
3587         //textureflags &= ~TEXF_FORCE_RELOAD;
3588
3589         skinframe->stain = NULL;
3590         skinframe->merged = NULL;
3591         skinframe->base = NULL;
3592         skinframe->pants = NULL;
3593         skinframe->shirt = NULL;
3594         skinframe->nmap = NULL;
3595         skinframe->gloss = NULL;
3596         skinframe->glow = NULL;
3597         skinframe->fog = NULL;
3598         skinframe->reflect = NULL;
3599         skinframe->hasalpha = false;
3600
3601         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3602         if (!skindata)
3603                 return NULL;
3604
3605         if (developer_loading.integer)
3606                 Con_Printf("loading quake skin \"%s\"\n", name);
3607
3608         // 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)
3609         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3610         memcpy(skinframe->qpixels, skindata, width*height);
3611         skinframe->qwidth = width;
3612         skinframe->qheight = height;
3613
3614         featuresmask = 0;
3615         for (i = 0;i < width * height;i++)
3616                 featuresmask |= palette_featureflags[skindata[i]];
3617
3618         skinframe->hasalpha = false;
3619         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3620         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3621         skinframe->qgeneratemerged = true;
3622         skinframe->qgeneratebase = skinframe->qhascolormapping;
3623         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3624
3625         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3626         //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]);
3627
3628         return skinframe;
3629 }
3630
3631 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3632 {
3633         int width;
3634         int height;
3635         unsigned char *skindata;
3636         char vabuf[1024];
3637
3638         if (!skinframe->qpixels)
3639                 return;
3640
3641         if (!skinframe->qhascolormapping)
3642                 colormapped = false;
3643
3644         if (colormapped)
3645         {
3646                 if (!skinframe->qgeneratebase)
3647                         return;
3648         }
3649         else
3650         {
3651                 if (!skinframe->qgeneratemerged)
3652                         return;
3653         }
3654
3655         width = skinframe->qwidth;
3656         height = skinframe->qheight;
3657         skindata = skinframe->qpixels;
3658
3659         if (skinframe->qgeneratenmap)
3660         {
3661                 unsigned char *temp1, *temp2;
3662                 skinframe->qgeneratenmap = false;
3663                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3664                 temp2 = temp1 + width * height * 4;
3665                 // use either a custom palette or the quake palette
3666                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3667                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3668                 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);
3669                 Mem_Free(temp1);
3670         }
3671
3672         if (skinframe->qgenerateglow)
3673         {
3674                 skinframe->qgenerateglow = false;
3675                 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
3676         }
3677
3678         if (colormapped)
3679         {
3680                 skinframe->qgeneratebase = false;
3681                 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);
3682                 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);
3683                 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);
3684         }
3685         else
3686         {
3687                 skinframe->qgeneratemerged = false;
3688                 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);
3689         }
3690
3691         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3692         {
3693                 Mem_Free(skinframe->qpixels);
3694                 skinframe->qpixels = NULL;
3695         }
3696 }
3697
3698 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)
3699 {
3700         int i;
3701         skinframe_t *skinframe;
3702         char vabuf[1024];
3703
3704         if (cls.state == ca_dedicated)
3705                 return NULL;
3706
3707         // if already loaded just return it, otherwise make a new skinframe
3708         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3709         if (skinframe->base)
3710                 return skinframe;
3711         textureflags &= ~TEXF_FORCE_RELOAD;
3712
3713         skinframe->stain = NULL;
3714         skinframe->merged = NULL;
3715         skinframe->base = NULL;
3716         skinframe->pants = NULL;
3717         skinframe->shirt = NULL;
3718         skinframe->nmap = NULL;
3719         skinframe->gloss = NULL;
3720         skinframe->glow = NULL;
3721         skinframe->fog = NULL;
3722         skinframe->reflect = NULL;
3723         skinframe->hasalpha = false;
3724
3725         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3726         if (!skindata)
3727                 return NULL;
3728
3729         if (developer_loading.integer)
3730                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3731
3732         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3733         if (textureflags & TEXF_ALPHA)
3734         {
3735                 for (i = 0;i < width * height;i++)
3736                 {
3737                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3738                         {
3739                                 skinframe->hasalpha = true;
3740                                 break;
3741                         }
3742                 }
3743                 if (r_loadfog && skinframe->hasalpha)
3744                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3745         }
3746
3747         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3748         //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]);
3749
3750         return skinframe;
3751 }
3752
3753 skinframe_t *R_SkinFrame_LoadMissing(void)
3754 {
3755         skinframe_t *skinframe;
3756
3757         if (cls.state == ca_dedicated)
3758                 return NULL;
3759
3760         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3761         skinframe->stain = NULL;
3762         skinframe->merged = NULL;
3763         skinframe->base = NULL;
3764         skinframe->pants = NULL;
3765         skinframe->shirt = NULL;
3766         skinframe->nmap = NULL;
3767         skinframe->gloss = NULL;
3768         skinframe->glow = NULL;
3769         skinframe->fog = NULL;
3770         skinframe->reflect = NULL;
3771         skinframe->hasalpha = false;
3772
3773         skinframe->avgcolor[0] = rand() / RAND_MAX;
3774         skinframe->avgcolor[1] = rand() / RAND_MAX;
3775         skinframe->avgcolor[2] = rand() / RAND_MAX;
3776         skinframe->avgcolor[3] = 1;
3777
3778         return skinframe;
3779 }
3780
3781 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3782 typedef struct suffixinfo_s
3783 {
3784         const char *suffix;
3785         qboolean flipx, flipy, flipdiagonal;
3786 }
3787 suffixinfo_t;
3788 static suffixinfo_t suffix[3][6] =
3789 {
3790         {
3791                 {"px",   false, false, false},
3792                 {"nx",   false, false, false},
3793                 {"py",   false, false, false},
3794                 {"ny",   false, false, false},
3795                 {"pz",   false, false, false},
3796                 {"nz",   false, false, false}
3797         },
3798         {
3799                 {"posx", false, false, false},
3800                 {"negx", false, false, false},
3801                 {"posy", false, false, false},
3802                 {"negy", false, false, false},
3803                 {"posz", false, false, false},
3804                 {"negz", false, false, false}
3805         },
3806         {
3807                 {"rt",    true, false,  true},
3808                 {"lf",   false,  true,  true},
3809                 {"ft",    true,  true, false},
3810                 {"bk",   false, false, false},
3811                 {"up",    true, false,  true},
3812                 {"dn",    true, false,  true}
3813         }
3814 };
3815
3816 static int componentorder[4] = {0, 1, 2, 3};
3817
3818 static rtexture_t *R_LoadCubemap(const char *basename)
3819 {
3820         int i, j, cubemapsize;
3821         unsigned char *cubemappixels, *image_buffer;
3822         rtexture_t *cubemaptexture;
3823         char name[256];
3824         // must start 0 so the first loadimagepixels has no requested width/height
3825         cubemapsize = 0;
3826         cubemappixels = NULL;
3827         cubemaptexture = NULL;
3828         // keep trying different suffix groups (posx, px, rt) until one loads
3829         for (j = 0;j < 3 && !cubemappixels;j++)
3830         {
3831                 // load the 6 images in the suffix group
3832                 for (i = 0;i < 6;i++)
3833                 {
3834                         // generate an image name based on the base and and suffix
3835                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3836                         // load it
3837                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3838                         {
3839                                 // an image loaded, make sure width and height are equal
3840                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3841                                 {
3842                                         // if this is the first image to load successfully, allocate the cubemap memory
3843                                         if (!cubemappixels && image_width >= 1)
3844                                         {
3845                                                 cubemapsize = image_width;
3846                                                 // note this clears to black, so unavailable sides are black
3847                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3848                                         }
3849                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3850                                         if (cubemappixels)
3851                                                 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);
3852                                 }
3853                                 else
3854                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3855                                 // free the image
3856                                 Mem_Free(image_buffer);
3857                         }
3858                 }
3859         }
3860         // if a cubemap loaded, upload it
3861         if (cubemappixels)
3862         {
3863                 if (developer_loading.integer)
3864                         Con_Printf("loading cubemap \"%s\"\n", basename);
3865
3866                 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);
3867                 Mem_Free(cubemappixels);
3868         }
3869         else
3870         {
3871                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3872                 if (developer_loading.integer)
3873                 {
3874                         Con_Printf("(tried tried images ");
3875                         for (j = 0;j < 3;j++)
3876                                 for (i = 0;i < 6;i++)
3877                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3878                         Con_Print(" and was unable to find any of them).\n");
3879                 }
3880         }
3881         return cubemaptexture;
3882 }
3883
3884 rtexture_t *R_GetCubemap(const char *basename)
3885 {
3886         int i;
3887         for (i = 0;i < r_texture_numcubemaps;i++)
3888                 if (r_texture_cubemaps[i] != NULL)
3889                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3890                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3891         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3892                 return r_texture_whitecube;
3893         r_texture_numcubemaps++;
3894         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3895         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3896         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3897         return r_texture_cubemaps[i]->texture;
3898 }
3899
3900 static void R_Main_FreeViewCache(void)
3901 {
3902         if (r_refdef.viewcache.entityvisible)
3903                 Mem_Free(r_refdef.viewcache.entityvisible);
3904         if (r_refdef.viewcache.world_pvsbits)
3905                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3906         if (r_refdef.viewcache.world_leafvisible)
3907                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3908         if (r_refdef.viewcache.world_surfacevisible)
3909                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3910         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3911 }
3912
3913 static void R_Main_ResizeViewCache(void)
3914 {
3915         int numentities = r_refdef.scene.numentities;
3916         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3917         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3918         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3919         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3920         if (r_refdef.viewcache.maxentities < numentities)
3921         {
3922                 r_refdef.viewcache.maxentities = numentities;
3923                 if (r_refdef.viewcache.entityvisible)
3924                         Mem_Free(r_refdef.viewcache.entityvisible);
3925                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3926         }
3927         if (r_refdef.viewcache.world_numclusters != numclusters)
3928         {
3929                 r_refdef.viewcache.world_numclusters = numclusters;
3930                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3931                 if (r_refdef.viewcache.world_pvsbits)
3932                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3933                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3934         }
3935         if (r_refdef.viewcache.world_numleafs != numleafs)
3936         {
3937                 r_refdef.viewcache.world_numleafs = numleafs;
3938                 if (r_refdef.viewcache.world_leafvisible)
3939                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3940                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3941         }
3942         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3943         {
3944                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3945                 if (r_refdef.viewcache.world_surfacevisible)
3946                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3947                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3948         }
3949 }
3950
3951 extern rtexture_t *loadingscreentexture;
3952 static void gl_main_start(void)
3953 {
3954         loadingscreentexture = NULL;
3955         r_texture_blanknormalmap = NULL;
3956         r_texture_white = NULL;
3957         r_texture_grey128 = NULL;
3958         r_texture_black = NULL;
3959         r_texture_whitecube = NULL;
3960         r_texture_normalizationcube = NULL;
3961         r_texture_fogattenuation = NULL;
3962         r_texture_fogheighttexture = NULL;
3963         r_texture_gammaramps = NULL;
3964         r_texture_numcubemaps = 0;
3965
3966         r_loaddds = r_texture_dds_load.integer != 0;
3967         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3968
3969         switch(vid.renderpath)
3970         {
3971         case RENDERPATH_GL20:
3972         case RENDERPATH_D3D9:
3973         case RENDERPATH_D3D10:
3974         case RENDERPATH_D3D11:
3975         case RENDERPATH_SOFT:
3976         case RENDERPATH_GLES2:
3977                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3978                 Cvar_SetValueQuick(&gl_combine, 1);
3979                 Cvar_SetValueQuick(&r_glsl, 1);
3980                 r_loadnormalmap = true;
3981                 r_loadgloss = true;
3982                 r_loadfog = false;
3983                 break;
3984         case RENDERPATH_GL13:
3985         case RENDERPATH_GLES1:
3986                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3987                 Cvar_SetValueQuick(&gl_combine, 1);
3988                 Cvar_SetValueQuick(&r_glsl, 0);
3989                 r_loadnormalmap = false;
3990                 r_loadgloss = false;
3991                 r_loadfog = true;
3992                 break;
3993         case RENDERPATH_GL11:
3994                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3995                 Cvar_SetValueQuick(&gl_combine, 0);
3996                 Cvar_SetValueQuick(&r_glsl, 0);
3997                 r_loadnormalmap = false;
3998                 r_loadgloss = false;
3999                 r_loadfog = true;
4000                 break;
4001         }
4002
4003         R_AnimCache_Free();
4004         R_FrameData_Reset();
4005
4006         r_numqueries = 0;
4007         r_maxqueries = 0;
4008         memset(r_queries, 0, sizeof(r_queries));
4009
4010         r_qwskincache = NULL;
4011         r_qwskincache_size = 0;
4012
4013         // due to caching of texture_t references, the collision cache must be reset
4014         Collision_Cache_Reset(true);
4015
4016         // set up r_skinframe loading system for textures
4017         memset(&r_skinframe, 0, sizeof(r_skinframe));
4018         r_skinframe.loadsequence = 1;
4019         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4020
4021         r_main_texturepool = R_AllocTexturePool();
4022         R_BuildBlankTextures();
4023         R_BuildNoTexture();
4024         if (vid.support.arb_texture_cube_map)
4025         {
4026                 R_BuildWhiteCube();
4027                 R_BuildNormalizationCube();
4028         }
4029         r_texture_fogattenuation = NULL;
4030         r_texture_fogheighttexture = NULL;
4031         r_texture_gammaramps = NULL;
4032         //r_texture_fogintensity = NULL;
4033         memset(&r_fb, 0, sizeof(r_fb));
4034         r_glsl_permutation = NULL;
4035         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4036         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4037         glslshaderstring = NULL;
4038 #ifdef SUPPORTD3D
4039         r_hlsl_permutation = NULL;
4040         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4041         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4042 #endif
4043         hlslshaderstring = NULL;
4044         memset(&r_svbsp, 0, sizeof (r_svbsp));
4045
4046         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4047         r_texture_numcubemaps = 0;
4048
4049         r_refdef.fogmasktable_density = 0;
4050 }
4051
4052 static void gl_main_shutdown(void)
4053 {
4054         R_AnimCache_Free();
4055         R_FrameData_Reset();
4056
4057         R_Main_FreeViewCache();
4058
4059         switch(vid.renderpath)
4060         {
4061         case RENDERPATH_GL11:
4062         case RENDERPATH_GL13:
4063         case RENDERPATH_GL20:
4064         case RENDERPATH_GLES1:
4065         case RENDERPATH_GLES2:
4066 #ifdef GL_SAMPLES_PASSED_ARB
4067                 if (r_maxqueries)
4068                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4069 #endif
4070                 break;
4071         case RENDERPATH_D3D9:
4072                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4073                 break;
4074         case RENDERPATH_D3D10:
4075                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4076                 break;
4077         case RENDERPATH_D3D11:
4078                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4079                 break;
4080         case RENDERPATH_SOFT:
4081                 break;
4082         }
4083
4084         r_numqueries = 0;
4085         r_maxqueries = 0;
4086         memset(r_queries, 0, sizeof(r_queries));
4087
4088         r_qwskincache = NULL;
4089         r_qwskincache_size = 0;
4090
4091         // clear out the r_skinframe state
4092         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4093         memset(&r_skinframe, 0, sizeof(r_skinframe));
4094
4095         if (r_svbsp.nodes)
4096                 Mem_Free(r_svbsp.nodes);
4097         memset(&r_svbsp, 0, sizeof (r_svbsp));
4098         R_FreeTexturePool(&r_main_texturepool);
4099         loadingscreentexture = NULL;
4100         r_texture_blanknormalmap = NULL;
4101         r_texture_white = NULL;
4102         r_texture_grey128 = NULL;
4103         r_texture_black = NULL;
4104         r_texture_whitecube = NULL;
4105         r_texture_normalizationcube = NULL;
4106         r_texture_fogattenuation = NULL;
4107         r_texture_fogheighttexture = NULL;
4108         r_texture_gammaramps = NULL;
4109         r_texture_numcubemaps = 0;
4110         //r_texture_fogintensity = NULL;
4111         memset(&r_fb, 0, sizeof(r_fb));
4112         R_GLSL_Restart_f();
4113
4114         r_glsl_permutation = NULL;
4115         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4116         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4117         glslshaderstring = NULL;
4118 #ifdef SUPPORTD3D
4119         r_hlsl_permutation = NULL;
4120         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4121         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4122 #endif
4123         hlslshaderstring = NULL;
4124 }
4125
4126 static void gl_main_newmap(void)
4127 {
4128         // FIXME: move this code to client
4129         char *entities, entname[MAX_QPATH];
4130         if (r_qwskincache)
4131                 Mem_Free(r_qwskincache);
4132         r_qwskincache = NULL;
4133         r_qwskincache_size = 0;
4134         if (cl.worldmodel)
4135         {
4136                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4137                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4138                 {
4139                         CL_ParseEntityLump(entities);
4140                         Mem_Free(entities);
4141                         return;
4142                 }
4143                 if (cl.worldmodel->brush.entities)
4144                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4145         }
4146         R_Main_FreeViewCache();
4147
4148         R_FrameData_Reset();
4149 }
4150
4151 void GL_Main_Init(void)
4152 {
4153         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4154
4155         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4156         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4157         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4158         if (gamemode == GAME_NEHAHRA)
4159         {
4160                 Cvar_RegisterVariable (&gl_fogenable);
4161                 Cvar_RegisterVariable (&gl_fogdensity);
4162                 Cvar_RegisterVariable (&gl_fogred);
4163                 Cvar_RegisterVariable (&gl_foggreen);
4164                 Cvar_RegisterVariable (&gl_fogblue);
4165                 Cvar_RegisterVariable (&gl_fogstart);
4166                 Cvar_RegisterVariable (&gl_fogend);
4167                 Cvar_RegisterVariable (&gl_skyclip);
4168         }
4169         Cvar_RegisterVariable(&r_motionblur);
4170         Cvar_RegisterVariable(&r_damageblur);
4171         Cvar_RegisterVariable(&r_motionblur_averaging);
4172         Cvar_RegisterVariable(&r_motionblur_randomize);
4173         Cvar_RegisterVariable(&r_motionblur_minblur);
4174         Cvar_RegisterVariable(&r_motionblur_maxblur);
4175         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4176         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4177         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4178         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4179         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4180         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4181         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4182         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4183         Cvar_RegisterVariable(&r_equalize_entities_by);
4184         Cvar_RegisterVariable(&r_equalize_entities_to);
4185         Cvar_RegisterVariable(&r_depthfirst);
4186         Cvar_RegisterVariable(&r_useinfinitefarclip);
4187         Cvar_RegisterVariable(&r_farclip_base);
4188         Cvar_RegisterVariable(&r_farclip_world);
4189         Cvar_RegisterVariable(&r_nearclip);
4190         Cvar_RegisterVariable(&r_deformvertexes);
4191         Cvar_RegisterVariable(&r_transparent);
4192         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4193         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4194         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4195         Cvar_RegisterVariable(&r_showoverdraw);
4196         Cvar_RegisterVariable(&r_showbboxes);
4197         Cvar_RegisterVariable(&r_showsurfaces);
4198         Cvar_RegisterVariable(&r_showtris);
4199         Cvar_RegisterVariable(&r_shownormals);
4200         Cvar_RegisterVariable(&r_showlighting);
4201         Cvar_RegisterVariable(&r_showshadowvolumes);
4202         Cvar_RegisterVariable(&r_showcollisionbrushes);
4203         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4204         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4205         Cvar_RegisterVariable(&r_showdisabledepthtest);
4206         Cvar_RegisterVariable(&r_drawportals);
4207         Cvar_RegisterVariable(&r_drawentities);
4208         Cvar_RegisterVariable(&r_draw2d);
4209         Cvar_RegisterVariable(&r_drawworld);
4210         Cvar_RegisterVariable(&r_cullentities_trace);
4211         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4212         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4213         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4214         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4215         Cvar_RegisterVariable(&r_sortentities);
4216         Cvar_RegisterVariable(&r_drawviewmodel);
4217         Cvar_RegisterVariable(&r_drawexteriormodel);
4218         Cvar_RegisterVariable(&r_speeds);
4219         Cvar_RegisterVariable(&r_fullbrights);
4220         Cvar_RegisterVariable(&r_wateralpha);
4221         Cvar_RegisterVariable(&r_dynamic);
4222         Cvar_RegisterVariable(&r_fakelight);
4223         Cvar_RegisterVariable(&r_fakelight_intensity);
4224         Cvar_RegisterVariable(&r_fullbright);
4225         Cvar_RegisterVariable(&r_shadows);
4226         Cvar_RegisterVariable(&r_shadows_darken);
4227         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4228         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4229         Cvar_RegisterVariable(&r_shadows_throwdistance);
4230         Cvar_RegisterVariable(&r_shadows_throwdirection);
4231         Cvar_RegisterVariable(&r_shadows_focus);
4232         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4233         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4234         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4235         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4236         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4237         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4238         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4239         Cvar_RegisterVariable(&r_fog_exp2);
4240         Cvar_RegisterVariable(&r_fog_clear);
4241         Cvar_RegisterVariable(&r_drawfog);
4242         Cvar_RegisterVariable(&r_transparentdepthmasking);
4243         Cvar_RegisterVariable(&r_transparent_sortmindist);
4244         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4245         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4246         Cvar_RegisterVariable(&r_texture_dds_load);
4247         Cvar_RegisterVariable(&r_texture_dds_save);
4248         Cvar_RegisterVariable(&r_textureunits);
4249         Cvar_RegisterVariable(&gl_combine);
4250         Cvar_RegisterVariable(&r_usedepthtextures);
4251         Cvar_RegisterVariable(&r_viewfbo);
4252         Cvar_RegisterVariable(&r_viewscale);
4253         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4254         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4255         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4256         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4257         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4258         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4259         Cvar_RegisterVariable(&r_glsl);
4260         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4261         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4262         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4263         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4264         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4265         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4266         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4267         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4268         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4269         Cvar_RegisterVariable(&r_glsl_postprocess);
4270         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4271         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4272         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4273         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4274         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4275         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4276         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4277         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4278         Cvar_RegisterVariable(&r_celshading);
4279         Cvar_RegisterVariable(&r_celoutlines);
4280
4281         Cvar_RegisterVariable(&r_water);
4282         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4283         Cvar_RegisterVariable(&r_water_clippingplanebias);
4284         Cvar_RegisterVariable(&r_water_refractdistort);
4285         Cvar_RegisterVariable(&r_water_reflectdistort);
4286         Cvar_RegisterVariable(&r_water_scissormode);
4287         Cvar_RegisterVariable(&r_water_lowquality);
4288         Cvar_RegisterVariable(&r_water_hideplayer);
4289         Cvar_RegisterVariable(&r_water_fbo);
4290
4291         Cvar_RegisterVariable(&r_lerpsprites);
4292         Cvar_RegisterVariable(&r_lerpmodels);
4293         Cvar_RegisterVariable(&r_lerplightstyles);
4294         Cvar_RegisterVariable(&r_waterscroll);
4295         Cvar_RegisterVariable(&r_bloom);
4296         Cvar_RegisterVariable(&r_bloom_colorscale);
4297         Cvar_RegisterVariable(&r_bloom_brighten);
4298         Cvar_RegisterVariable(&r_bloom_blur);
4299         Cvar_RegisterVariable(&r_bloom_resolution);
4300         Cvar_RegisterVariable(&r_bloom_colorexponent);
4301         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4302         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4303         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4304         Cvar_RegisterVariable(&r_hdr_glowintensity);
4305         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4306         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4307         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4308         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4309         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4310         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4311         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4312         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4313         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4314         Cvar_RegisterVariable(&developer_texturelogging);
4315         Cvar_RegisterVariable(&gl_lightmaps);
4316         Cvar_RegisterVariable(&r_test);
4317         Cvar_RegisterVariable(&r_batch_multidraw);
4318         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4319         Cvar_RegisterVariable(&r_glsl_saturation);
4320         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4321         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4322         Cvar_RegisterVariable(&r_framedatasize);
4323         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4324                 Cvar_SetValue("r_fullbrights", 0);
4325         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4326 }
4327
4328 void Render_Init(void)
4329 {
4330         gl_backend_init();
4331         R_Textures_Init();
4332         GL_Main_Init();
4333         Font_Init();
4334         GL_Draw_Init();
4335         R_Shadow_Init();
4336         R_Sky_Init();
4337         GL_Surf_Init();
4338         Sbar_Init();
4339         R_Particles_Init();
4340         R_Explosion_Init();
4341         R_LightningBeams_Init();
4342         Mod_RenderInit();
4343 }
4344
4345 /*
4346 ===============
4347 GL_Init
4348 ===============
4349 */
4350 #ifndef USE_GLES2
4351 extern char *ENGINE_EXTENSIONS;
4352 void GL_Init (void)
4353 {
4354         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4355         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4356         gl_version = (const char *)qglGetString(GL_VERSION);
4357         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4358
4359         if (!gl_extensions)
4360                 gl_extensions = "";
4361         if (!gl_platformextensions)
4362                 gl_platformextensions = "";
4363
4364         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4365         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4366         Con_Printf("GL_VERSION: %s\n", gl_version);
4367         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4368         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4369
4370         VID_CheckExtensions();
4371
4372         // LordHavoc: report supported extensions
4373         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4374
4375         // clear to black (loading plaque will be seen over this)
4376         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4377 }
4378 #endif
4379
4380 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4381 {
4382         int i;
4383         mplane_t *p;
4384         if (r_trippy.integer)
4385                 return false;
4386         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4387         {
4388                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4389                 if (i == 4)
4390                         continue;
4391                 p = r_refdef.view.frustum + i;
4392                 switch(p->signbits)
4393                 {
4394                 default:
4395                 case 0:
4396                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4397                                 return true;
4398                         break;
4399                 case 1:
4400                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4401                                 return true;
4402                         break;
4403                 case 2:
4404                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4405                                 return true;
4406                         break;
4407                 case 3:
4408                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4409                                 return true;
4410                         break;
4411                 case 4:
4412                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4413                                 return true;
4414                         break;
4415                 case 5:
4416                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4417                                 return true;
4418                         break;
4419                 case 6:
4420                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4421                                 return true;
4422                         break;
4423                 case 7:
4424                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4425                                 return true;
4426                         break;
4427                 }
4428         }
4429         return false;
4430 }
4431
4432 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4433 {
4434         int i;
4435         const mplane_t *p;
4436         if (r_trippy.integer)
4437                 return false;
4438         for (i = 0;i < numplanes;i++)
4439         {
4440                 p = planes + i;
4441                 switch(p->signbits)
4442                 {
4443                 default:
4444                 case 0:
4445                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4446                                 return true;
4447                         break;
4448                 case 1:
4449                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4450                                 return true;
4451                         break;
4452                 case 2:
4453                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4454                                 return true;
4455                         break;
4456                 case 3:
4457                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4458                                 return true;
4459                         break;
4460                 case 4:
4461                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4462                                 return true;
4463                         break;
4464                 case 5:
4465                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4466                                 return true;
4467                         break;
4468                 case 6:
4469                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4470                                 return true;
4471                         break;
4472                 case 7:
4473                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4474                                 return true;
4475                         break;
4476                 }
4477         }
4478         return false;
4479 }
4480
4481 //==================================================================================
4482
4483 // LordHavoc: this stores temporary data used within the same frame
4484
4485 typedef struct r_framedata_mem_s
4486 {
4487         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4488         size_t size; // how much usable space
4489         size_t current; // how much space in use
4490         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4491         size_t wantedsize; // how much space was allocated
4492         unsigned char *data; // start of real data (16byte aligned)
4493 }
4494 r_framedata_mem_t;
4495
4496 static r_framedata_mem_t *r_framedata_mem;
4497
4498 void R_FrameData_Reset(void)
4499 {
4500         while (r_framedata_mem)
4501         {
4502                 r_framedata_mem_t *next = r_framedata_mem->purge;
4503                 Mem_Free(r_framedata_mem);
4504                 r_framedata_mem = next;
4505         }
4506 }
4507
4508 static void R_FrameData_Resize(void)
4509 {
4510         size_t wantedsize;
4511         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4512         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4513         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4514         {
4515                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4516                 newmem->wantedsize = wantedsize;
4517                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4518                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4519                 newmem->current = 0;
4520                 newmem->mark = 0;
4521                 newmem->purge = r_framedata_mem;
4522                 r_framedata_mem = newmem;
4523         }
4524 }
4525
4526 void R_FrameData_NewFrame(void)
4527 {
4528         R_FrameData_Resize();
4529         if (!r_framedata_mem)
4530                 return;
4531         // if we ran out of space on the last frame, free the old memory now
4532         while (r_framedata_mem->purge)
4533         {
4534                 // repeatedly remove the second item in the list, leaving only head
4535                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4536                 Mem_Free(r_framedata_mem->purge);
4537                 r_framedata_mem->purge = next;
4538         }
4539         // reset the current mem pointer
4540         r_framedata_mem->current = 0;
4541         r_framedata_mem->mark = 0;
4542 }
4543
4544 void *R_FrameData_Alloc(size_t size)
4545 {
4546         void *data;
4547
4548         // align to 16 byte boundary - the data pointer is already aligned, so we
4549         // only need to ensure the size of every allocation is also aligned
4550         size = (size + 15) & ~15;
4551
4552         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4553         {
4554                 // emergency - we ran out of space, allocate more memory
4555                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4556                 R_FrameData_Resize();
4557         }
4558
4559         data = r_framedata_mem->data + r_framedata_mem->current;
4560         r_framedata_mem->current += size;
4561
4562         // count the usage for stats
4563         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4564         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4565
4566         return (void *)data;
4567 }
4568
4569 void *R_FrameData_Store(size_t size, void *data)
4570 {
4571         void *d = R_FrameData_Alloc(size);
4572         if (d && data)
4573                 memcpy(d, data, size);
4574         return d;
4575 }
4576
4577 void R_FrameData_SetMark(void)
4578 {
4579         if (!r_framedata_mem)
4580                 return;
4581         r_framedata_mem->mark = r_framedata_mem->current;
4582 }
4583
4584 void R_FrameData_ReturnToMark(void)
4585 {
4586         if (!r_framedata_mem)
4587                 return;
4588         r_framedata_mem->current = r_framedata_mem->mark;
4589 }
4590
4591 //==================================================================================
4592
4593 // LordHavoc: animcache originally written by Echon, rewritten since then
4594
4595 /**
4596  * Animation cache prevents re-generating mesh data for an animated model
4597  * multiple times in one frame for lighting, shadowing, reflections, etc.
4598  */
4599
4600 void R_AnimCache_Free(void)
4601 {
4602 }
4603
4604 void R_AnimCache_ClearCache(void)
4605 {
4606         int i;
4607         entity_render_t *ent;
4608
4609         for (i = 0;i < r_refdef.scene.numentities;i++)
4610         {
4611                 ent = r_refdef.scene.entities[i];
4612                 ent->animcache_vertex3f = NULL;
4613                 ent->animcache_normal3f = NULL;
4614                 ent->animcache_svector3f = NULL;
4615                 ent->animcache_tvector3f = NULL;
4616                 ent->animcache_vertexmesh = NULL;
4617                 ent->animcache_vertex3fbuffer = NULL;
4618                 ent->animcache_vertexmeshbuffer = NULL;
4619         }
4620 }
4621
4622 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4623 {
4624         int i;
4625
4626         // check if we need the meshbuffers
4627         if (!vid.useinterleavedarrays)
4628                 return;
4629
4630         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4631                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4632         // TODO: upload vertex3f buffer?
4633         if (ent->animcache_vertexmesh)
4634         {
4635                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4636                 for (i = 0;i < numvertices;i++)
4637                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4638                 if (ent->animcache_svector3f)
4639                         for (i = 0;i < numvertices;i++)
4640                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4641                 if (ent->animcache_tvector3f)
4642                         for (i = 0;i < numvertices;i++)
4643                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4644                 if (ent->animcache_normal3f)
4645                         for (i = 0;i < numvertices;i++)
4646                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4647                 // TODO: upload vertexmeshbuffer?
4648         }
4649 }
4650
4651 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4652 {
4653         dp_model_t *model = ent->model;
4654         int numvertices;
4655         // see if it's already cached this frame
4656         if (ent->animcache_vertex3f)
4657         {
4658                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4659                 if (wantnormals || wanttangents)
4660                 {
4661                         if (ent->animcache_normal3f)
4662                                 wantnormals = false;
4663                         if (ent->animcache_svector3f)
4664                                 wanttangents = false;
4665                         if (wantnormals || wanttangents)
4666                         {
4667                                 numvertices = model->surfmesh.num_vertices;
4668                                 if (wantnormals)
4669                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4670                                 if (wanttangents)
4671                                 {
4672                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4673                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4674                                 }
4675                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4676                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4677                         }
4678                 }
4679         }
4680         else
4681         {
4682                 // see if this ent is worth caching
4683                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4684                         return false;
4685                 // get some memory for this entity and generate mesh data
4686                 numvertices = model->surfmesh.num_vertices;
4687                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4688                 if (wantnormals)
4689                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4690                 if (wanttangents)
4691                 {
4692                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4693                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4694                 }
4695                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4696                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4697         }
4698         return true;
4699 }
4700
4701 void R_AnimCache_CacheVisibleEntities(void)
4702 {
4703         int i;
4704         qboolean wantnormals = true;
4705         qboolean wanttangents = !r_showsurfaces.integer;
4706
4707         switch(vid.renderpath)
4708         {
4709         case RENDERPATH_GL20:
4710         case RENDERPATH_D3D9:
4711         case RENDERPATH_D3D10:
4712         case RENDERPATH_D3D11:
4713         case RENDERPATH_GLES2:
4714                 break;
4715         case RENDERPATH_GL11:
4716         case RENDERPATH_GL13:
4717         case RENDERPATH_GLES1:
4718                 wanttangents = false;
4719                 break;
4720         case RENDERPATH_SOFT:
4721                 break;
4722         }
4723
4724         if (r_shownormals.integer)
4725                 wanttangents = wantnormals = true;
4726
4727         // TODO: thread this
4728         // NOTE: R_PrepareRTLights() also caches entities
4729
4730         for (i = 0;i < r_refdef.scene.numentities;i++)
4731                 if (r_refdef.viewcache.entityvisible[i])
4732                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4733 }
4734
4735 //==================================================================================
4736
4737 extern cvar_t r_overheadsprites_pushback;
4738
4739 static void R_View_UpdateEntityLighting (void)
4740 {
4741         int i;
4742         entity_render_t *ent;
4743         vec3_t tempdiffusenormal, avg;
4744         vec_t f, fa, fd, fdd;
4745         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4746
4747         for (i = 0;i < r_refdef.scene.numentities;i++)
4748         {
4749                 ent = r_refdef.scene.entities[i];
4750
4751                 // skip unseen models
4752                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4753                         continue;
4754
4755                 // skip bsp models
4756                 if (ent->model && ent->model == cl.worldmodel)
4757                 {
4758                         // TODO: use modellight for r_ambient settings on world?
4759                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4760                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4761                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4762                         continue;
4763                 }
4764                 
4765                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4766                 {
4767                         // aleady updated by CSQC
4768                         // TODO: force modellight on BSP models in this case?
4769                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4770                 }
4771                 else
4772                 {
4773                         // fetch the lighting from the worldmodel data
4774                         VectorClear(ent->modellight_ambient);
4775                         VectorClear(ent->modellight_diffuse);
4776                         VectorClear(tempdiffusenormal);
4777                         if (ent->flags & RENDER_LIGHT)
4778                         {
4779                                 vec3_t org;
4780                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4781
4782                                 // complete lightning for lit sprites
4783                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4784                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4785                                 {
4786                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4787                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4788                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4789                                 }
4790                                 else
4791                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4792
4793                                 if(ent->flags & RENDER_EQUALIZE)
4794                                 {
4795                                         // first fix up ambient lighting...
4796                                         if(r_equalize_entities_minambient.value > 0)
4797                                         {
4798                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4799                                                 if(fd > 0)
4800                                                 {
4801                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4802                                                         if(fa < r_equalize_entities_minambient.value * fd)
4803                                                         {
4804                                                                 // solve:
4805                                                                 //   fa'/fd' = minambient
4806                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4807                                                                 //   ...
4808                                                                 //   fa' = fd' * minambient
4809                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4810                                                                 //   ...
4811                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4812                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4813                                                                 //   ...
4814                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4815                                                                 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
4816                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4817                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4818                                                         }
4819                                                 }
4820                                         }
4821
4822                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4823                                         {
4824                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4825                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4826                                                 f = fa + 0.25 * fd;
4827                                                 if(f > 0)
4828                                                 {
4829                                                         // adjust brightness and saturation to target
4830                                                         avg[0] = avg[1] = avg[2] = fa / f;
4831                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4832                                                         avg[0] = avg[1] = avg[2] = fd / f;
4833                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4834                                                 }
4835                                         }
4836                                 }
4837                         }
4838                         else // highly rare
4839                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4840                 }
4841
4842                 // move the light direction into modelspace coordinates for lighting code
4843                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4844                 if(VectorLength2(ent->modellight_lightdir) == 0)
4845                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4846                 VectorNormalize(ent->modellight_lightdir);
4847         }
4848 }
4849
4850 #define MAX_LINEOFSIGHTTRACES 64
4851
4852 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4853 {
4854         int i;
4855         vec3_t boxmins, boxmaxs;
4856         vec3_t start;
4857         vec3_t end;
4858         dp_model_t *model = r_refdef.scene.worldmodel;
4859
4860         if (!model || !model->brush.TraceLineOfSight)
4861                 return true;
4862
4863         // expand the box a little
4864         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4865         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4866         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4867         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4868         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4869         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4870
4871         // return true if eye is inside enlarged box
4872         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4873                 return true;
4874
4875         // try center
4876         VectorCopy(eye, start);
4877         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4878         if (model->brush.TraceLineOfSight(model, start, end))
4879                 return true;
4880
4881         // try various random positions
4882         for (i = 0;i < numsamples;i++)
4883         {
4884                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4885                 if (model->brush.TraceLineOfSight(model, start, end))
4886                         return true;
4887         }
4888
4889         return false;
4890 }
4891
4892
4893 static void R_View_UpdateEntityVisible (void)
4894 {
4895         int i;
4896         int renderimask;
4897         int samples;
4898         entity_render_t *ent;
4899
4900         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4901                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4902                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4903                 :                                                          RENDER_EXTERIORMODEL;
4904         if (!r_drawviewmodel.integer)
4905                 renderimask |= RENDER_VIEWMODEL;
4906         if (!r_drawexteriormodel.integer)
4907                 renderimask |= RENDER_EXTERIORMODEL;
4908         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4909         {
4910                 // worldmodel can check visibility
4911                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4912                 for (i = 0;i < r_refdef.scene.numentities;i++)
4913                 {
4914                         ent = r_refdef.scene.entities[i];
4915                         if (!(ent->flags & renderimask))
4916                         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)))
4917                         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))
4918                                 r_refdef.viewcache.entityvisible[i] = true;
4919                 }
4920         }
4921         else
4922         {
4923                 // no worldmodel or it can't check visibility
4924                 for (i = 0;i < r_refdef.scene.numentities;i++)
4925                 {
4926                         ent = r_refdef.scene.entities[i];
4927                         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));
4928                 }
4929         }
4930         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4931                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4932         {
4933                 for (i = 0;i < r_refdef.scene.numentities;i++)
4934                 {
4935                         if (!r_refdef.viewcache.entityvisible[i])
4936                                 continue;
4937                         ent = r_refdef.scene.entities[i];
4938                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4939                         {
4940                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4941                                 if (samples < 0)
4942                                         continue; // temp entities do pvs only
4943                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4944                                         ent->last_trace_visibility = realtime;
4945                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4946                                         r_refdef.viewcache.entityvisible[i] = 0;
4947                         }
4948                 }
4949         }
4950 }
4951
4952 /// only used if skyrendermasked, and normally returns false
4953 static int R_DrawBrushModelsSky (void)
4954 {
4955         int i, sky;
4956         entity_render_t *ent;
4957
4958         sky = false;
4959         for (i = 0;i < r_refdef.scene.numentities;i++)
4960         {
4961                 if (!r_refdef.viewcache.entityvisible[i])
4962                         continue;
4963                 ent = r_refdef.scene.entities[i];
4964                 if (!ent->model || !ent->model->DrawSky)
4965                         continue;
4966                 ent->model->DrawSky(ent);
4967                 sky = true;
4968         }
4969         return sky;
4970 }
4971
4972 static void R_DrawNoModel(entity_render_t *ent);
4973 static void R_DrawModels(void)
4974 {
4975         int i;
4976         entity_render_t *ent;
4977
4978         for (i = 0;i < r_refdef.scene.numentities;i++)
4979         {
4980                 if (!r_refdef.viewcache.entityvisible[i])
4981                         continue;
4982                 ent = r_refdef.scene.entities[i];
4983                 r_refdef.stats.entities++;
4984                 /*
4985                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4986                 {
4987                         vec3_t f, l, u, o;
4988                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4989                         Con_Printf("R_DrawModels\n");
4990                         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]);
4991                         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);
4992                         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);
4993                 }
4994                 */
4995                 if (ent->model && ent->model->Draw != NULL)
4996                         ent->model->Draw(ent);
4997                 else
4998                         R_DrawNoModel(ent);
4999         }
5000 }
5001
5002 static void R_DrawModelsDepth(void)
5003 {
5004         int i;
5005         entity_render_t *ent;
5006
5007         for (i = 0;i < r_refdef.scene.numentities;i++)
5008         {
5009                 if (!r_refdef.viewcache.entityvisible[i])
5010                         continue;
5011                 ent = r_refdef.scene.entities[i];
5012                 if (ent->model && ent->model->DrawDepth != NULL)
5013                         ent->model->DrawDepth(ent);
5014         }
5015 }
5016
5017 static void R_DrawModelsDebug(void)
5018 {
5019         int i;
5020         entity_render_t *ent;
5021
5022         for (i = 0;i < r_refdef.scene.numentities;i++)
5023         {
5024                 if (!r_refdef.viewcache.entityvisible[i])
5025                         continue;
5026                 ent = r_refdef.scene.entities[i];
5027                 if (ent->model && ent->model->DrawDebug != NULL)
5028                         ent->model->DrawDebug(ent);
5029         }
5030 }
5031
5032 static void R_DrawModelsAddWaterPlanes(void)
5033 {
5034         int i;
5035         entity_render_t *ent;
5036
5037         for (i = 0;i < r_refdef.scene.numentities;i++)
5038         {
5039                 if (!r_refdef.viewcache.entityvisible[i])
5040                         continue;
5041                 ent = r_refdef.scene.entities[i];
5042                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5043                         ent->model->DrawAddWaterPlanes(ent);
5044         }
5045 }
5046
5047 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}};
5048
5049 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5050 {
5051         if (r_hdr_irisadaptation.integer)
5052         {
5053                 vec3_t p;
5054                 vec3_t ambient;
5055                 vec3_t diffuse;
5056                 vec3_t diffusenormal;
5057                 vec3_t forward;
5058                 vec_t brightness = 0.0f;
5059                 vec_t goal;
5060                 vec_t current;
5061                 vec_t d;
5062                 int c;
5063                 VectorCopy(r_refdef.view.forward, forward);
5064                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5065                 {
5066                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5067                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5068                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5069                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5070                         d = DotProduct(forward, diffusenormal);
5071                         brightness += VectorLength(ambient);
5072                         if (d > 0)
5073                                 brightness += d * VectorLength(diffuse);
5074                 }
5075                 brightness *= 1.0f / c;
5076                 brightness += 0.00001f; // make sure it's never zero
5077                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5078                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5079                 current = r_hdr_irisadaptation_value.value;
5080                 if (current < goal)
5081                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5082                 else if (current > goal)
5083                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5084                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5085                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5086         }
5087         else if (r_hdr_irisadaptation_value.value != 1.0f)
5088                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5089 }
5090
5091 static void R_View_SetFrustum(const int *scissor)
5092 {
5093         int i;
5094         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5095         vec3_t forward, left, up, origin, v;
5096
5097         if(scissor)
5098         {
5099                 // flipped x coordinates (because x points left here)
5100                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5101                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5102
5103                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5104                 switch(vid.renderpath)
5105                 {
5106                         case RENDERPATH_D3D9:
5107                         case RENDERPATH_D3D10:
5108                         case RENDERPATH_D3D11:
5109                                 // non-flipped y coordinates
5110                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5111                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5112                                 break;
5113                         case RENDERPATH_SOFT:
5114                         case RENDERPATH_GL11:
5115                         case RENDERPATH_GL13:
5116                         case RENDERPATH_GL20:
5117                         case RENDERPATH_GLES1:
5118                         case RENDERPATH_GLES2:
5119                                 // non-flipped y coordinates
5120                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5121                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5122                                 break;
5123                 }
5124         }
5125
5126         // we can't trust r_refdef.view.forward and friends in reflected scenes
5127         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5128
5129 #if 0
5130         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5131         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5132         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5133         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5134         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5135         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5136         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5137         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5138         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5139         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5140         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5141         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5142 #endif
5143
5144 #if 0
5145         zNear = r_refdef.nearclip;
5146         nudge = 1.0 - 1.0 / (1<<23);
5147         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5148         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5149         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5150         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5151         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5152         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5153         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5154         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5155 #endif
5156
5157
5158
5159 #if 0
5160         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5161         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5162         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5163         r_refdef.view.frustum[0].dist = m[15] - m[12];
5164
5165         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5166         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5167         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5168         r_refdef.view.frustum[1].dist = m[15] + m[12];
5169
5170         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5171         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5172         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5173         r_refdef.view.frustum[2].dist = m[15] - m[13];
5174
5175         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5176         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5177         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5178         r_refdef.view.frustum[3].dist = m[15] + m[13];
5179
5180         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5181         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5182         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5183         r_refdef.view.frustum[4].dist = m[15] - m[14];
5184
5185         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5186         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5187         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5188         r_refdef.view.frustum[5].dist = m[15] + m[14];
5189 #endif
5190
5191         if (r_refdef.view.useperspective)
5192         {
5193                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5194                 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]);
5195                 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]);
5196                 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]);
5197                 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]);
5198
5199                 // then the normals from the corners relative to origin
5200                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5201                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5202                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5203                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5204
5205                 // in a NORMAL view, forward cross left == up
5206                 // in a REFLECTED view, forward cross left == down
5207                 // so our cross products above need to be adjusted for a left handed coordinate system
5208                 CrossProduct(forward, left, v);
5209                 if(DotProduct(v, up) < 0)
5210                 {
5211                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5212                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5213                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5214                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5215                 }
5216
5217                 // Leaving those out was a mistake, those were in the old code, and they
5218                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5219                 // I couldn't reproduce it after adding those normalizations. --blub
5220                 VectorNormalize(r_refdef.view.frustum[0].normal);
5221                 VectorNormalize(r_refdef.view.frustum[1].normal);
5222                 VectorNormalize(r_refdef.view.frustum[2].normal);
5223                 VectorNormalize(r_refdef.view.frustum[3].normal);
5224
5225                 // make the corners absolute
5226                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5227                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5228                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5229                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5230
5231                 // one more normal
5232                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5233
5234                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5235                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5236                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5237                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5238                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5239         }
5240         else
5241         {
5242                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5243                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5244                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5245                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5246                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5247                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5248                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5249                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5250                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5251                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5252         }
5253         r_refdef.view.numfrustumplanes = 5;
5254
5255         if (r_refdef.view.useclipplane)
5256         {
5257                 r_refdef.view.numfrustumplanes = 6;
5258                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5259         }
5260
5261         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5262                 PlaneClassify(r_refdef.view.frustum + i);
5263
5264         // LordHavoc: note to all quake engine coders, Quake had a special case
5265         // for 90 degrees which assumed a square view (wrong), so I removed it,
5266         // Quake2 has it disabled as well.
5267
5268         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5269         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5270         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5271         //PlaneClassify(&frustum[0]);
5272
5273         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5274         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5275         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5276         //PlaneClassify(&frustum[1]);
5277
5278         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5279         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5280         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5281         //PlaneClassify(&frustum[2]);
5282
5283         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5284         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5285         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5286         //PlaneClassify(&frustum[3]);
5287
5288         // nearclip plane
5289         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5290         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5291         //PlaneClassify(&frustum[4]);
5292 }
5293
5294 static void R_View_UpdateWithScissor(const int *myscissor)
5295 {
5296         R_Main_ResizeViewCache();
5297         R_View_SetFrustum(myscissor);
5298         R_View_WorldVisibility(r_refdef.view.useclipplane);
5299         R_View_UpdateEntityVisible();
5300         R_View_UpdateEntityLighting();
5301 }
5302
5303 static void R_View_Update(void)
5304 {
5305         R_Main_ResizeViewCache();
5306         R_View_SetFrustum(NULL);
5307         R_View_WorldVisibility(r_refdef.view.useclipplane);
5308         R_View_UpdateEntityVisible();
5309         R_View_UpdateEntityLighting();
5310 }
5311
5312 float viewscalefpsadjusted = 1.0f;
5313
5314 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5315 {
5316         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5317         scale = bound(0.03125f, scale, 1.0f);
5318         *outwidth = (int)ceil(width * scale);
5319         *outheight = (int)ceil(height * scale);
5320 }
5321
5322 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5323 {
5324         const float *customclipplane = NULL;
5325         float plane[4];
5326         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5327         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5328         {
5329                 // LordHavoc: couldn't figure out how to make this approach the
5330                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5331                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5332                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5333                         dist = r_refdef.view.clipplane.dist;
5334                 plane[0] = r_refdef.view.clipplane.normal[0];
5335                 plane[1] = r_refdef.view.clipplane.normal[1];
5336                 plane[2] = r_refdef.view.clipplane.normal[2];
5337                 plane[3] = -dist;
5338                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5339         }
5340
5341         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5342         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5343
5344         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5345         if (!r_refdef.view.useperspective)
5346                 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);
5347         else if (vid.stencil && r_useinfinitefarclip.integer)
5348                 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);
5349         else
5350                 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);
5351         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5352         R_SetViewport(&r_refdef.view.viewport);
5353         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5354         {
5355                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5356                 float screenplane[4];
5357                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5358                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5359                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5360                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5361                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5362         }
5363 }
5364
5365 void R_EntityMatrix(const matrix4x4_t *matrix)
5366 {
5367         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5368         {
5369                 gl_modelmatrixchanged = false;
5370                 gl_modelmatrix = *matrix;
5371                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5372                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5373                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5374                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5375                 CHECKGLERROR
5376                 switch(vid.renderpath)
5377                 {
5378                 case RENDERPATH_D3D9:
5379 #ifdef SUPPORTD3D
5380                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5381                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5382 #endif
5383                         break;
5384                 case RENDERPATH_D3D10:
5385                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5386                         break;
5387                 case RENDERPATH_D3D11:
5388                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5389                         break;
5390                 case RENDERPATH_GL11:
5391                 case RENDERPATH_GL13:
5392                 case RENDERPATH_GLES1:
5393                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5394                         break;
5395                 case RENDERPATH_SOFT:
5396                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5397                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5398                         break;
5399                 case RENDERPATH_GL20:
5400                 case RENDERPATH_GLES2:
5401                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5402                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5403                         break;
5404                 }
5405         }
5406 }
5407
5408 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5409 {
5410         r_viewport_t viewport;
5411
5412         CHECKGLERROR
5413
5414         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5415         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);
5416         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5417         R_SetViewport(&viewport);
5418         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5419         GL_Color(1, 1, 1, 1);
5420         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5421         GL_BlendFunc(GL_ONE, GL_ZERO);
5422         GL_ScissorTest(false);
5423         GL_DepthMask(false);
5424         GL_DepthRange(0, 1);
5425         GL_DepthTest(false);
5426         GL_DepthFunc(GL_LEQUAL);
5427         R_EntityMatrix(&identitymatrix);
5428         R_Mesh_ResetTextureState();
5429         GL_PolygonOffset(0, 0);
5430         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5431         switch(vid.renderpath)
5432         {
5433         case RENDERPATH_GL11:
5434         case RENDERPATH_GL13:
5435         case RENDERPATH_GL20:
5436         case RENDERPATH_GLES1:
5437         case RENDERPATH_GLES2:
5438                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5439                 break;
5440         case RENDERPATH_D3D9:
5441         case RENDERPATH_D3D10:
5442         case RENDERPATH_D3D11:
5443         case RENDERPATH_SOFT:
5444                 break;
5445         }
5446         GL_CullFace(GL_NONE);
5447
5448         CHECKGLERROR
5449 }
5450
5451 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5452 {
5453         DrawQ_Finish();
5454
5455         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5456 }
5457
5458 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5459 {
5460         DrawQ_Finish();
5461
5462         R_SetupView(true, fbo, depthtexture, colortexture);
5463         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5464         GL_Color(1, 1, 1, 1);
5465         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5466         GL_BlendFunc(GL_ONE, GL_ZERO);
5467         GL_ScissorTest(true);
5468         GL_DepthMask(true);
5469         GL_DepthRange(0, 1);
5470         GL_DepthTest(true);
5471         GL_DepthFunc(GL_LEQUAL);
5472         R_EntityMatrix(&identitymatrix);
5473         R_Mesh_ResetTextureState();
5474         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5475         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5476         switch(vid.renderpath)
5477         {
5478         case RENDERPATH_GL11:
5479         case RENDERPATH_GL13:
5480         case RENDERPATH_GL20:
5481         case RENDERPATH_GLES1:
5482         case RENDERPATH_GLES2:
5483                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5484                 break;
5485         case RENDERPATH_D3D9:
5486         case RENDERPATH_D3D10:
5487         case RENDERPATH_D3D11:
5488         case RENDERPATH_SOFT:
5489                 break;
5490         }
5491         GL_CullFace(r_refdef.view.cullface_back);
5492 }
5493
5494 /*
5495 ================
5496 R_RenderView_UpdateViewVectors
5497 ================
5498 */
5499 void R_RenderView_UpdateViewVectors(void)
5500 {
5501         // break apart the view matrix into vectors for various purposes
5502         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5503         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5504         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5505         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5506         // make an inverted copy of the view matrix for tracking sprites
5507         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5508 }
5509
5510 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5511 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5512
5513 static void R_Water_StartFrame(void)
5514 {
5515         int i;
5516         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5517         r_waterstate_waterplane_t *p;
5518         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;
5519
5520         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5521                 return;
5522
5523         switch(vid.renderpath)
5524         {
5525         case RENDERPATH_GL20:
5526         case RENDERPATH_D3D9:
5527         case RENDERPATH_D3D10:
5528         case RENDERPATH_D3D11:
5529         case RENDERPATH_SOFT:
5530         case RENDERPATH_GLES2:
5531                 break;
5532         case RENDERPATH_GL11:
5533         case RENDERPATH_GL13:
5534         case RENDERPATH_GLES1:
5535                 return;
5536         }
5537
5538         // set waterwidth and waterheight to the water resolution that will be
5539         // used (often less than the screen resolution for faster rendering)
5540         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5541
5542         // calculate desired texture sizes
5543         // can't use water if the card does not support the texture size
5544         if (!r_water.integer || r_showsurfaces.integer)
5545                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5546         else if (vid.support.arb_texture_non_power_of_two)
5547         {
5548                 texturewidth = waterwidth;
5549                 textureheight = waterheight;
5550                 camerawidth = waterwidth;
5551                 cameraheight = waterheight;
5552         }
5553         else
5554         {
5555                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5556                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5557                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5558                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5559         }
5560
5561         // allocate textures as needed
5562         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))
5563         {
5564                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5565                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5566                 {
5567                         if (p->texture_refraction)
5568                                 R_FreeTexture(p->texture_refraction);
5569                         p->texture_refraction = NULL;
5570                         if (p->fbo_refraction)
5571                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5572                         p->fbo_refraction = 0;
5573                         if (p->texture_reflection)
5574                                 R_FreeTexture(p->texture_reflection);
5575                         p->texture_reflection = NULL;
5576                         if (p->fbo_reflection)
5577                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5578                         p->fbo_reflection = 0;
5579                         if (p->texture_camera)
5580                                 R_FreeTexture(p->texture_camera);
5581                         p->texture_camera = NULL;
5582                         if (p->fbo_camera)
5583                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5584                         p->fbo_camera = 0;
5585                 }
5586                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5587                 r_fb.water.texturewidth = texturewidth;
5588                 r_fb.water.textureheight = textureheight;
5589                 r_fb.water.camerawidth = camerawidth;
5590                 r_fb.water.cameraheight = cameraheight;
5591         }
5592
5593         if (r_fb.water.texturewidth)
5594         {
5595                 int scaledwidth, scaledheight;
5596
5597                 r_fb.water.enabled = true;
5598
5599                 // water resolution is usually reduced
5600                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5601                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5602                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5603
5604                 // set up variables that will be used in shader setup
5605                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5606                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5607                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5608                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5609         }
5610
5611         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5612         r_fb.water.numwaterplanes = 0;
5613 }
5614
5615 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5616 {
5617         int planeindex, bestplaneindex, vertexindex;
5618         vec3_t mins, maxs, normal, center, v, n;
5619         vec_t planescore, bestplanescore;
5620         mplane_t plane;
5621         r_waterstate_waterplane_t *p;
5622         texture_t *t = R_GetCurrentTexture(surface->texture);
5623
5624         rsurface.texture = t;
5625         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5626         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5627         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5628                 return;
5629         // average the vertex normals, find the surface bounds (after deformvertexes)
5630         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5631         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5632         VectorCopy(n, normal);
5633         VectorCopy(v, mins);
5634         VectorCopy(v, maxs);
5635         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5636         {
5637                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5638                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5639                 VectorAdd(normal, n, normal);
5640                 mins[0] = min(mins[0], v[0]);
5641                 mins[1] = min(mins[1], v[1]);
5642                 mins[2] = min(mins[2], v[2]);
5643                 maxs[0] = max(maxs[0], v[0]);
5644                 maxs[1] = max(maxs[1], v[1]);
5645                 maxs[2] = max(maxs[2], v[2]);
5646         }
5647         VectorNormalize(normal);
5648         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5649
5650         VectorCopy(normal, plane.normal);
5651         VectorNormalize(plane.normal);
5652         plane.dist = DotProduct(center, plane.normal);
5653         PlaneClassify(&plane);
5654         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5655         {
5656                 // skip backfaces (except if nocullface is set)
5657 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5658 //                      return;
5659                 VectorNegate(plane.normal, plane.normal);
5660                 plane.dist *= -1;
5661                 PlaneClassify(&plane);
5662         }
5663
5664
5665         // find a matching plane if there is one
5666         bestplaneindex = -1;
5667         bestplanescore = 1048576.0f;
5668         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5669         {
5670                 if(p->camera_entity == t->camera_entity)
5671                 {
5672                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5673                         if (bestplaneindex < 0 || bestplanescore > planescore)
5674                         {
5675                                 bestplaneindex = planeindex;
5676                                 bestplanescore = planescore;
5677                         }
5678                 }
5679         }
5680         planeindex = bestplaneindex;
5681         p = r_fb.water.waterplanes + planeindex;
5682
5683         // if this surface does not fit any known plane rendered this frame, add one
5684         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5685         {
5686                 // store the new plane
5687                 planeindex = r_fb.water.numwaterplanes++;
5688                 p = r_fb.water.waterplanes + planeindex;
5689                 p->plane = plane;
5690                 // clear materialflags and pvs
5691                 p->materialflags = 0;
5692                 p->pvsvalid = false;
5693                 p->camera_entity = t->camera_entity;
5694                 VectorCopy(mins, p->mins);
5695                 VectorCopy(maxs, p->maxs);
5696         }
5697         else
5698         {
5699                 // merge mins/maxs when we're adding this surface to the plane
5700                 p->mins[0] = min(p->mins[0], mins[0]);
5701                 p->mins[1] = min(p->mins[1], mins[1]);
5702                 p->mins[2] = min(p->mins[2], mins[2]);
5703                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5704                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5705                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5706         }
5707         // merge this surface's materialflags into the waterplane
5708         p->materialflags |= t->currentmaterialflags;
5709         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5710         {
5711                 // merge this surface's PVS into the waterplane
5712                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5713                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5714                 {
5715                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5716                         p->pvsvalid = true;
5717                 }
5718         }
5719 }
5720
5721 extern cvar_t r_drawparticles;
5722 extern cvar_t r_drawdecals;
5723
5724 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5725 {
5726         int myscissor[4];
5727         r_refdef_view_t originalview;
5728         r_refdef_view_t myview;
5729         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;
5730         r_waterstate_waterplane_t *p;
5731         vec3_t visorigin;
5732         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;
5733         char vabuf[1024];
5734
5735         originalview = r_refdef.view;
5736
5737         // lowquality hack, temporarily shut down some cvars and restore afterwards
5738         qualityreduction = r_water_lowquality.integer;
5739         if (qualityreduction > 0)
5740         {
5741                 if (qualityreduction >= 1)
5742                 {
5743                         old_r_shadows = r_shadows.integer;
5744                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5745                         old_r_dlight = r_shadow_realtime_dlight.integer;
5746                         Cvar_SetValueQuick(&r_shadows, 0);
5747                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5748                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5749                 }
5750                 if (qualityreduction >= 2)
5751                 {
5752                         old_r_dynamic = r_dynamic.integer;
5753                         old_r_particles = r_drawparticles.integer;
5754                         old_r_decals = r_drawdecals.integer;
5755                         Cvar_SetValueQuick(&r_dynamic, 0);
5756                         Cvar_SetValueQuick(&r_drawparticles, 0);
5757                         Cvar_SetValueQuick(&r_drawdecals, 0);
5758                 }
5759         }
5760
5761         // make sure enough textures are allocated
5762         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5763         {
5764                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5765                 {
5766                         if (!p->texture_refraction)
5767                                 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);
5768                         if (!p->texture_refraction)
5769                                 goto error;
5770                         if (usewaterfbo)
5771                         {
5772                                 if (r_fb.water.depthtexture == NULL)
5773                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5774                                 if (p->fbo_refraction == 0)
5775                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5776                         }
5777                 }
5778                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5779                 {
5780                         if (!p->texture_camera)
5781                                 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);
5782                         if (!p->texture_camera)
5783                                 goto error;
5784                         if (usewaterfbo)
5785                         {
5786                                 if (r_fb.water.depthtexture == NULL)
5787                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5788                                 if (p->fbo_camera == 0)
5789                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5790                         }
5791                 }
5792
5793                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5794                 {
5795                         if (!p->texture_reflection)
5796                                 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);
5797                         if (!p->texture_reflection)
5798                                 goto error;
5799                         if (usewaterfbo)
5800                         {
5801                                 if (r_fb.water.depthtexture == NULL)
5802                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5803                                 if (p->fbo_reflection == 0)
5804                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5805                         }
5806                 }
5807         }
5808
5809         // render views
5810         r_refdef.view = originalview;
5811         r_refdef.view.showdebug = false;
5812         r_refdef.view.width = r_fb.water.waterwidth;
5813         r_refdef.view.height = r_fb.water.waterheight;
5814         r_refdef.view.useclipplane = true;
5815         myview = r_refdef.view;
5816         r_fb.water.renderingscene = true;
5817         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5818         {
5819                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5820                 {
5821                         r_refdef.view = myview;
5822                         if(r_water_scissormode.integer)
5823                         {
5824                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5825                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5826                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5827                         }
5828
5829                         // render reflected scene and copy into texture
5830                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5831                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5832                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5833                         r_refdef.view.clipplane = p->plane;
5834                         // reverse the cullface settings for this render
5835                         r_refdef.view.cullface_front = GL_FRONT;
5836                         r_refdef.view.cullface_back = GL_BACK;
5837                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5838                         {
5839                                 r_refdef.view.usecustompvs = true;
5840                                 if (p->pvsvalid)
5841                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5842                                 else
5843                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5844                         }
5845
5846                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5847                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5848                         R_ClearScreen(r_refdef.fogenabled);
5849                         if(r_water_scissormode.integer & 2)
5850                                 R_View_UpdateWithScissor(myscissor);
5851                         else
5852                                 R_View_Update();
5853                         R_AnimCache_CacheVisibleEntities();
5854                         if(r_water_scissormode.integer & 1)
5855                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5856                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5857
5858                         if (!p->fbo_reflection)
5859                                 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);
5860                         r_fb.water.hideplayer = false;
5861                 }
5862
5863                 // render the normal view scene and copy into texture
5864                 // (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)
5865                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5866                 {
5867                         r_refdef.view = myview;
5868                         if(r_water_scissormode.integer)
5869                         {
5870                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5871                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5872                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5873                         }
5874
5875                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5876
5877                         r_refdef.view.clipplane = p->plane;
5878                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5879                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5880
5881                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5882                         {
5883                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5884                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5885                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5886                                 R_RenderView_UpdateViewVectors();
5887                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5888                                 {
5889                                         r_refdef.view.usecustompvs = true;
5890                                         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);
5891                                 }
5892                         }
5893
5894                         PlaneClassify(&r_refdef.view.clipplane);
5895
5896                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5897                         R_ClearScreen(r_refdef.fogenabled);
5898                         if(r_water_scissormode.integer & 2)
5899                                 R_View_UpdateWithScissor(myscissor);
5900                         else
5901                                 R_View_Update();
5902                         R_AnimCache_CacheVisibleEntities();
5903                         if(r_water_scissormode.integer & 1)
5904                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5905                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5906
5907                         if (!p->fbo_refraction)
5908                                 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);
5909                         r_fb.water.hideplayer = false;
5910                 }
5911                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5912                 {
5913                         r_refdef.view = myview;
5914
5915                         r_refdef.view.clipplane = p->plane;
5916                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5917                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5918
5919                         r_refdef.view.width = r_fb.water.camerawidth;
5920                         r_refdef.view.height = r_fb.water.cameraheight;
5921                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5922                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5923                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5924                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5925
5926                         if(p->camera_entity)
5927                         {
5928                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5929                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5930                         }
5931
5932                         // note: all of the view is used for displaying... so
5933                         // there is no use in scissoring
5934
5935                         // reverse the cullface settings for this render
5936                         r_refdef.view.cullface_front = GL_FRONT;
5937                         r_refdef.view.cullface_back = GL_BACK;
5938                         // also reverse the view matrix
5939                         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
5940                         R_RenderView_UpdateViewVectors();
5941                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5942                         {
5943                                 r_refdef.view.usecustompvs = true;
5944                                 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);
5945                         }
5946                         
5947                         // camera needs no clipplane
5948                         r_refdef.view.useclipplane = false;
5949
5950                         PlaneClassify(&r_refdef.view.clipplane);
5951
5952                         r_fb.water.hideplayer = false;
5953
5954                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5955                         R_ClearScreen(r_refdef.fogenabled);
5956                         R_View_Update();
5957                         R_AnimCache_CacheVisibleEntities();
5958                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5959
5960                         if (!p->fbo_camera)
5961                                 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);
5962                         r_fb.water.hideplayer = false;
5963                 }
5964
5965         }
5966         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5967         r_fb.water.renderingscene = false;
5968         r_refdef.view = originalview;
5969         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5970         if (!r_fb.water.depthtexture)
5971                 R_ClearScreen(r_refdef.fogenabled);
5972         R_View_Update();
5973         R_AnimCache_CacheVisibleEntities();
5974         goto finish;
5975 error:
5976         r_refdef.view = originalview;
5977         r_fb.water.renderingscene = false;
5978         Cvar_SetValueQuick(&r_water, 0);
5979         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5980 finish:
5981         // lowquality hack, restore cvars
5982         if (qualityreduction > 0)
5983         {
5984                 if (qualityreduction >= 1)
5985                 {
5986                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5987                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5988                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5989                 }
5990                 if (qualityreduction >= 2)
5991                 {
5992                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5993                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5994                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5995                 }
5996         }
5997 }
5998
5999 static void R_Bloom_StartFrame(void)
6000 {
6001         int i;
6002         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6003         int viewwidth, viewheight;
6004         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6005         textype_t textype = TEXTYPE_COLORBUFFER;
6006
6007         switch (vid.renderpath)
6008         {
6009         case RENDERPATH_GL20:
6010                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6011                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6012                 {
6013                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6014                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6015                 }
6016                 break;
6017         case RENDERPATH_GL11:
6018         case RENDERPATH_GL13:
6019         case RENDERPATH_GLES1:
6020         case RENDERPATH_GLES2:
6021         case RENDERPATH_D3D9:
6022         case RENDERPATH_D3D10:
6023         case RENDERPATH_D3D11:
6024                 r_fb.usedepthtextures = false;
6025                 break;
6026         case RENDERPATH_SOFT:
6027                 r_fb.usedepthtextures = true;
6028                 break;
6029         }
6030
6031         if (r_viewscale_fpsscaling.integer)
6032         {
6033                 double actualframetime;
6034                 double targetframetime;
6035                 double adjust;
6036                 actualframetime = r_refdef.lastdrawscreentime;
6037                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6038                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6039                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6040                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6041                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6042                 viewscalefpsadjusted += adjust;
6043                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6044         }
6045         else
6046                 viewscalefpsadjusted = 1.0f;
6047
6048         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6049
6050         switch(vid.renderpath)
6051         {
6052         case RENDERPATH_GL20:
6053         case RENDERPATH_D3D9:
6054         case RENDERPATH_D3D10:
6055         case RENDERPATH_D3D11:
6056         case RENDERPATH_SOFT:
6057         case RENDERPATH_GLES2:
6058                 break;
6059         case RENDERPATH_GL11:
6060         case RENDERPATH_GL13:
6061         case RENDERPATH_GLES1:
6062                 return;
6063         }
6064
6065         // set bloomwidth and bloomheight to the bloom resolution that will be
6066         // used (often less than the screen resolution for faster rendering)
6067         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6068         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6069         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6070         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6071         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6072
6073         // calculate desired texture sizes
6074         if (vid.support.arb_texture_non_power_of_two)
6075         {
6076                 screentexturewidth = vid.width;
6077                 screentextureheight = vid.height;
6078                 bloomtexturewidth = r_fb.bloomwidth;
6079                 bloomtextureheight = r_fb.bloomheight;
6080         }
6081         else
6082         {
6083                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6084                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6085                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6086                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6087         }
6088
6089         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))
6090         {
6091                 Cvar_SetValueQuick(&r_bloom, 0);
6092                 Cvar_SetValueQuick(&r_motionblur, 0);
6093                 Cvar_SetValueQuick(&r_damageblur, 0);
6094         }
6095
6096         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6097          && !r_bloom.integer
6098          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6099          && !useviewfbo
6100          && r_viewscale.value == 1.0f
6101          && !r_viewscale_fpsscaling.integer)
6102                 screentexturewidth = screentextureheight = 0;
6103         if (!r_bloom.integer)
6104                 bloomtexturewidth = bloomtextureheight = 0;
6105
6106         // allocate textures as needed
6107         if (r_fb.screentexturewidth != screentexturewidth
6108          || r_fb.screentextureheight != screentextureheight
6109          || r_fb.bloomtexturewidth != bloomtexturewidth
6110          || r_fb.bloomtextureheight != bloomtextureheight
6111          || r_fb.textype != textype
6112          || useviewfbo != (r_fb.fbo != 0))
6113         {
6114                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6115                 {
6116                         if (r_fb.bloomtexture[i])
6117                                 R_FreeTexture(r_fb.bloomtexture[i]);
6118                         r_fb.bloomtexture[i] = NULL;
6119
6120                         if (r_fb.bloomfbo[i])
6121                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6122                         r_fb.bloomfbo[i] = 0;
6123                 }
6124
6125                 if (r_fb.fbo)
6126                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6127                 r_fb.fbo = 0;
6128
6129                 if (r_fb.colortexture)
6130                         R_FreeTexture(r_fb.colortexture);
6131                 r_fb.colortexture = NULL;
6132
6133                 if (r_fb.depthtexture)
6134                         R_FreeTexture(r_fb.depthtexture);
6135                 r_fb.depthtexture = NULL;
6136
6137                 if (r_fb.ghosttexture)
6138                         R_FreeTexture(r_fb.ghosttexture);
6139                 r_fb.ghosttexture = NULL;
6140
6141                 r_fb.screentexturewidth = screentexturewidth;
6142                 r_fb.screentextureheight = screentextureheight;
6143                 r_fb.bloomtexturewidth = bloomtexturewidth;
6144                 r_fb.bloomtextureheight = bloomtextureheight;
6145                 r_fb.textype = textype;
6146
6147                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6148                 {
6149                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6150                                 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);
6151                         r_fb.ghosttexture_valid = false;
6152                         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);
6153                         if (useviewfbo)
6154                         {
6155                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6156                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6157                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6158                         }
6159                 }
6160
6161                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6162                 {
6163                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6164                         {
6165                                 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);
6166                                 if (useviewfbo)
6167                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6168                         }
6169                 }
6170         }
6171
6172         // bloom texture is a different resolution
6173         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6174         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6175         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6176         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6177         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6178
6179         // set up a texcoord array for the full resolution screen image
6180         // (we have to keep this around to copy back during final render)
6181         r_fb.screentexcoord2f[0] = 0;
6182         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6183         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6184         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6185         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6186         r_fb.screentexcoord2f[5] = 0;
6187         r_fb.screentexcoord2f[6] = 0;
6188         r_fb.screentexcoord2f[7] = 0;
6189
6190         if(r_fb.fbo) 
6191         {
6192                 for (i = 1;i < 8;i += 2)
6193                 {
6194                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6195                 }
6196         }
6197
6198         // set up a texcoord array for the reduced resolution bloom image
6199         // (which will be additive blended over the screen image)
6200         r_fb.bloomtexcoord2f[0] = 0;
6201         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6202         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6203         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6204         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6205         r_fb.bloomtexcoord2f[5] = 0;
6206         r_fb.bloomtexcoord2f[6] = 0;
6207         r_fb.bloomtexcoord2f[7] = 0;
6208
6209         switch(vid.renderpath)
6210         {
6211         case RENDERPATH_GL11:
6212         case RENDERPATH_GL13:
6213         case RENDERPATH_GL20:
6214         case RENDERPATH_SOFT:
6215         case RENDERPATH_GLES1:
6216         case RENDERPATH_GLES2:
6217                 break;
6218         case RENDERPATH_D3D9:
6219         case RENDERPATH_D3D10:
6220         case RENDERPATH_D3D11:
6221                 for (i = 0;i < 4;i++)
6222                 {
6223                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6224                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6225                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6226                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6227                 }
6228                 break;
6229         }
6230
6231         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6232
6233         if (r_fb.fbo)
6234                 r_refdef.view.clear = true;
6235 }
6236
6237 static void R_Bloom_MakeTexture(void)
6238 {
6239         int x, range, dir;
6240         float xoffset, yoffset, r, brighten;
6241         rtexture_t *intex;
6242         float colorscale = r_bloom_colorscale.value;
6243
6244         r_refdef.stats.bloom++;
6245     
6246 #if 0
6247     // this copy is unnecessary since it happens in R_BlendView already
6248         if (!r_fb.fbo)
6249         {
6250                 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);
6251                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6252         }
6253 #endif
6254
6255         // scale down screen texture to the bloom texture size
6256         CHECKGLERROR
6257         r_fb.bloomindex = 0;
6258         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6259         R_SetViewport(&r_fb.bloomviewport);
6260         GL_DepthTest(false);
6261         GL_BlendFunc(GL_ONE, GL_ZERO);
6262         GL_Color(colorscale, colorscale, colorscale, 1);
6263         // 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...
6264         switch(vid.renderpath)
6265         {
6266         case RENDERPATH_GL11:
6267         case RENDERPATH_GL13:
6268         case RENDERPATH_GL20:
6269         case RENDERPATH_GLES1:
6270         case RENDERPATH_GLES2:
6271         case RENDERPATH_SOFT:
6272                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6273                 break;
6274         case RENDERPATH_D3D9:
6275         case RENDERPATH_D3D10:
6276         case RENDERPATH_D3D11:
6277                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6278                 break;
6279         }
6280         // TODO: do boxfilter scale-down in shader?
6281         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6282         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6283         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6284
6285         // we now have a properly scaled bloom image
6286         if (!r_fb.bloomfbo[r_fb.bloomindex])
6287         {
6288                 // copy it into the bloom texture
6289                 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);
6290                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6291         }
6292
6293         // multiply bloom image by itself as many times as desired
6294         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6295         {
6296                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6297                 r_fb.bloomindex ^= 1;
6298                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6299                 x *= 2;
6300                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6301                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6302                 {
6303                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6304                         GL_Color(r,r,r,1); // apply fix factor
6305                 }
6306                 else
6307                 {
6308                         if(x <= 2)
6309                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6310                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6311                         GL_Color(1,1,1,1); // no fix factor supported here
6312                 }
6313                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6314                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6315                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6316                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6317
6318                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6319                 {
6320                         // copy the darkened image to a texture
6321                         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);
6322                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6323                 }
6324         }
6325
6326         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6327         brighten = r_bloom_brighten.value;
6328         brighten = sqrt(brighten);
6329         if(range >= 1)
6330                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6331
6332         for (dir = 0;dir < 2;dir++)
6333         {
6334                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6335                 r_fb.bloomindex ^= 1;
6336                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6337                 // blend on at multiple vertical offsets to achieve a vertical blur
6338                 // TODO: do offset blends using GLSL
6339                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6340                 GL_BlendFunc(GL_ONE, GL_ZERO);
6341                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6342                 for (x = -range;x <= range;x++)
6343                 {
6344                         if (!dir){xoffset = 0;yoffset = x;}
6345                         else {xoffset = x;yoffset = 0;}
6346                         xoffset /= (float)r_fb.bloomtexturewidth;
6347                         yoffset /= (float)r_fb.bloomtextureheight;
6348                         // compute a texcoord array with the specified x and y offset
6349                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6350                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6351                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6352                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6353                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6354                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6355                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6356                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6357                         // this r value looks like a 'dot' particle, fading sharply to
6358                         // black at the edges
6359                         // (probably not realistic but looks good enough)
6360                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6361                         //r = brighten/(range*2+1);
6362                         r = brighten / (range * 2 + 1);
6363                         if(range >= 1)
6364                                 r *= (1 - x*x/(float)(range*range));
6365                         GL_Color(r, r, r, 1);
6366                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6367                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6368                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6369                         GL_BlendFunc(GL_ONE, GL_ONE);
6370                 }
6371
6372                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6373                 {
6374                         // copy the vertically or horizontally blurred bloom view to a texture
6375                         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);
6376                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6377                 }
6378         }
6379 }
6380
6381 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6382 {
6383         unsigned int permutation;
6384         float uservecs[4][4];
6385
6386         R_EntityMatrix(&identitymatrix);
6387
6388         switch (vid.renderpath)
6389         {
6390         case RENDERPATH_GL20:
6391         case RENDERPATH_D3D9:
6392         case RENDERPATH_D3D10:
6393         case RENDERPATH_D3D11:
6394         case RENDERPATH_SOFT:
6395         case RENDERPATH_GLES2:
6396                 permutation =
6397                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6398                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6399                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6400                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6401                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6402
6403                 if (r_fb.colortexture)
6404                 {
6405                         if (!r_fb.fbo)
6406                         {
6407                                 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);
6408                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6409                         }
6410
6411                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6412                         {
6413                                 // declare variables
6414                                 float blur_factor, blur_mouseaccel, blur_velocity;
6415                                 static float blur_average; 
6416                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6417
6418                                 // set a goal for the factoring
6419                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6420                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6421                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6422                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6423                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6424                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6425
6426                                 // from the goal, pick an averaged value between goal and last value
6427                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6428                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6429
6430                                 // enforce minimum amount of blur 
6431                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6432
6433                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6434
6435                                 // calculate values into a standard alpha
6436                                 cl.motionbluralpha = 1 - exp(-
6437                                                 (
6438                                                  (r_motionblur.value * blur_factor / 80)
6439                                                  +
6440                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6441                                                 )
6442                                                 /
6443                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6444                                           );
6445
6446                                 // randomization for the blur value to combat persistent ghosting
6447                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6448                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6449
6450                                 // apply the blur
6451                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6452                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6453                                 {
6454                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6455                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6456                                         switch(vid.renderpath)
6457                                         {
6458                                         case RENDERPATH_GL11:
6459                                         case RENDERPATH_GL13:
6460                                         case RENDERPATH_GL20:
6461                                         case RENDERPATH_GLES1:
6462                                         case RENDERPATH_GLES2:
6463                                         case RENDERPATH_SOFT:
6464                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6465                                                 break;
6466                                         case RENDERPATH_D3D9:
6467                                         case RENDERPATH_D3D10:
6468                                         case RENDERPATH_D3D11:
6469                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6470                                                 break;
6471                                         }
6472                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6473                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6474                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6475                                 }
6476
6477                                 // updates old view angles for next pass
6478                                 VectorCopy(cl.viewangles, blur_oldangles);
6479
6480                                 // copy view into the ghost texture
6481                                 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);
6482                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6483                                 r_fb.ghosttexture_valid = true;
6484                         }
6485                 }
6486                 else
6487                 {
6488                         // no r_fb.colortexture means we're rendering to the real fb
6489                         // we may still have to do view tint...
6490                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6491                         {
6492                                 // apply a color tint to the whole view
6493                                 R_ResetViewRendering2D(0, NULL, NULL);
6494                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6495                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6496                                 R_SetupShader_Generic_NoTexture(false, true);
6497                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6498                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6499                         }
6500                         break; // no screen processing, no bloom, skip it
6501                 }
6502
6503                 if (r_fb.bloomtexture[0])
6504                 {
6505                         // make the bloom texture
6506                         R_Bloom_MakeTexture();
6507                 }
6508
6509 #if _MSC_VER >= 1400
6510 #define sscanf sscanf_s
6511 #endif
6512                 memset(uservecs, 0, sizeof(uservecs));
6513                 if (r_glsl_postprocess_uservec1_enable.integer)
6514                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6515                 if (r_glsl_postprocess_uservec2_enable.integer)
6516                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6517                 if (r_glsl_postprocess_uservec3_enable.integer)
6518                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6519                 if (r_glsl_postprocess_uservec4_enable.integer)
6520                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6521
6522                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6523                 GL_Color(1, 1, 1, 1);
6524                 GL_BlendFunc(GL_ONE, GL_ZERO);
6525
6526                 switch(vid.renderpath)
6527                 {
6528                 case RENDERPATH_GL20:
6529                 case RENDERPATH_GLES2:
6530                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6531                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6532                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6533                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6534                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6535                         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]);
6536                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6537                         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]);
6538                         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]);
6539                         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]);
6540                         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]);
6541                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6542                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6543                         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);
6544                         break;
6545                 case RENDERPATH_D3D9:
6546 #ifdef SUPPORTD3D
6547                         // 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...
6548                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6549                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6550                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6551                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6552                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6553                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6554                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6555                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6556                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6557                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6558                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6559                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6560                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6561                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6562 #endif
6563                         break;
6564                 case RENDERPATH_D3D10:
6565                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6566                         break;
6567                 case RENDERPATH_D3D11:
6568                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6569                         break;
6570                 case RENDERPATH_SOFT:
6571                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6572                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6573                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6574                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6575                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6576                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6577                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6578                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6579                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6580                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6581                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6582                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6583                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6584                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6585                         break;
6586                 default:
6587                         break;
6588                 }
6589                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6590                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6591                 break;
6592         case RENDERPATH_GL11:
6593         case RENDERPATH_GL13:
6594         case RENDERPATH_GLES1:
6595                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6596                 {
6597                         // apply a color tint to the whole view
6598                         R_ResetViewRendering2D(0, NULL, NULL);
6599                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6600                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6601                         R_SetupShader_Generic_NoTexture(false, true);
6602                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6603                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6604                 }
6605                 break;
6606         }
6607 }
6608
6609 matrix4x4_t r_waterscrollmatrix;
6610
6611 void R_UpdateFog(void)
6612 {
6613         // Nehahra fog
6614         if (gamemode == GAME_NEHAHRA)
6615         {
6616                 if (gl_fogenable.integer)
6617                 {
6618                         r_refdef.oldgl_fogenable = true;
6619                         r_refdef.fog_density = gl_fogdensity.value;
6620                         r_refdef.fog_red = gl_fogred.value;
6621                         r_refdef.fog_green = gl_foggreen.value;
6622                         r_refdef.fog_blue = gl_fogblue.value;
6623                         r_refdef.fog_alpha = 1;
6624                         r_refdef.fog_start = 0;
6625                         r_refdef.fog_end = gl_skyclip.value;
6626                         r_refdef.fog_height = 1<<30;
6627                         r_refdef.fog_fadedepth = 128;
6628                 }
6629                 else if (r_refdef.oldgl_fogenable)
6630                 {
6631                         r_refdef.oldgl_fogenable = false;
6632                         r_refdef.fog_density = 0;
6633                         r_refdef.fog_red = 0;
6634                         r_refdef.fog_green = 0;
6635                         r_refdef.fog_blue = 0;
6636                         r_refdef.fog_alpha = 0;
6637                         r_refdef.fog_start = 0;
6638                         r_refdef.fog_end = 0;
6639                         r_refdef.fog_height = 1<<30;
6640                         r_refdef.fog_fadedepth = 128;
6641                 }
6642         }
6643
6644         // fog parms
6645         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6646         r_refdef.fog_start = max(0, r_refdef.fog_start);
6647         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6648
6649         if (r_refdef.fog_density && r_drawfog.integer)
6650         {
6651                 r_refdef.fogenabled = true;
6652                 // this is the point where the fog reaches 0.9986 alpha, which we
6653                 // consider a good enough cutoff point for the texture
6654                 // (0.9986 * 256 == 255.6)
6655                 if (r_fog_exp2.integer)
6656                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6657                 else
6658                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6659                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6660                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6661                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6662                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6663                         R_BuildFogHeightTexture();
6664                 // fog color was already set
6665                 // update the fog texture
6666                 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)
6667                         R_BuildFogTexture();
6668                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6669                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6670         }
6671         else
6672                 r_refdef.fogenabled = false;
6673
6674         // fog color
6675         if (r_refdef.fog_density)
6676         {
6677                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6678                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6679                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6680
6681                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6682                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6683                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6684                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6685
6686                 {
6687                         vec3_t fogvec;
6688                         VectorCopy(r_refdef.fogcolor, fogvec);
6689                         //   color.rgb *= ContrastBoost * SceneBrightness;
6690                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6691                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6692                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6693                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6694                 }
6695         }
6696 }
6697
6698 void R_UpdateVariables(void)
6699 {
6700         R_Textures_Frame();
6701
6702         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6703
6704         r_refdef.farclip = r_farclip_base.value;
6705         if (r_refdef.scene.worldmodel)
6706                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6707         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6708
6709         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6710                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6711         r_refdef.polygonfactor = 0;
6712         r_refdef.polygonoffset = 0;
6713         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6714         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6715
6716         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6717         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6718         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6719         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6720         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6721         if (FAKELIGHT_ENABLED)
6722         {
6723                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6724         }
6725         else if (r_refdef.scene.worldmodel)
6726         {
6727                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6728         }
6729         if (r_showsurfaces.integer)
6730         {
6731                 r_refdef.scene.rtworld = false;
6732                 r_refdef.scene.rtworldshadows = false;
6733                 r_refdef.scene.rtdlight = false;
6734                 r_refdef.scene.rtdlightshadows = false;
6735                 r_refdef.lightmapintensity = 0;
6736         }
6737
6738         switch(vid.renderpath)
6739         {
6740         case RENDERPATH_GL20:
6741         case RENDERPATH_D3D9:
6742         case RENDERPATH_D3D10:
6743         case RENDERPATH_D3D11:
6744         case RENDERPATH_SOFT:
6745         case RENDERPATH_GLES2:
6746                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6747                 {
6748                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6749                         {
6750                                 // build GLSL gamma texture
6751 #define RAMPWIDTH 256
6752                                 unsigned short ramp[RAMPWIDTH * 3];
6753                                 unsigned char rampbgr[RAMPWIDTH][4];
6754                                 int i;
6755
6756                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6757
6758                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6759                                 for(i = 0; i < RAMPWIDTH; ++i)
6760                                 {
6761                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6762                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6763                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6764                                         rampbgr[i][3] = 0;
6765                                 }
6766                                 if (r_texture_gammaramps)
6767                                 {
6768                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6769                                 }
6770                                 else
6771                                 {
6772                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6773                                 }
6774                         }
6775                 }
6776                 else
6777                 {
6778                         // remove GLSL gamma texture
6779                 }
6780                 break;
6781         case RENDERPATH_GL11:
6782         case RENDERPATH_GL13:
6783         case RENDERPATH_GLES1:
6784                 break;
6785         }
6786 }
6787
6788 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6789 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6790 /*
6791 ================
6792 R_SelectScene
6793 ================
6794 */
6795 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6796         if( scenetype != r_currentscenetype ) {
6797                 // store the old scenetype
6798                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6799                 r_currentscenetype = scenetype;
6800                 // move in the new scene
6801                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6802         }
6803 }
6804
6805 /*
6806 ================
6807 R_GetScenePointer
6808 ================
6809 */
6810 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6811 {
6812         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6813         if( scenetype == r_currentscenetype ) {
6814                 return &r_refdef.scene;
6815         } else {
6816                 return &r_scenes_store[ scenetype ];
6817         }
6818 }
6819
6820 static int R_SortEntities_Compare(const void *ap, const void *bp)
6821 {
6822         const entity_render_t *a = *(const entity_render_t **)ap;
6823         const entity_render_t *b = *(const entity_render_t **)bp;
6824
6825         // 1. compare model
6826         if(a->model < b->model)
6827                 return -1;
6828         if(a->model > b->model)
6829                 return +1;
6830
6831         // 2. compare skin
6832         // TODO possibly calculate the REAL skinnum here first using
6833         // skinscenes?
6834         if(a->skinnum < b->skinnum)
6835                 return -1;
6836         if(a->skinnum > b->skinnum)
6837                 return +1;
6838
6839         // everything we compared is equal
6840         return 0;
6841 }
6842 static void R_SortEntities(void)
6843 {
6844         // below or equal 2 ents, sorting never gains anything
6845         if(r_refdef.scene.numentities <= 2)
6846                 return;
6847         // sort
6848         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6849 }
6850
6851 /*
6852 ================
6853 R_RenderView
6854 ================
6855 */
6856 int dpsoftrast_test;
6857 extern cvar_t r_shadow_bouncegrid;
6858 void R_RenderView(void)
6859 {
6860         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6861         int fbo;
6862         rtexture_t *depthtexture;
6863         rtexture_t *colortexture;
6864
6865         dpsoftrast_test = r_test.integer;
6866
6867         if (r_timereport_active)
6868                 R_TimeReport("start");
6869         r_textureframe++; // used only by R_GetCurrentTexture
6870         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6871
6872         if(R_CompileShader_CheckStaticParms())
6873                 R_GLSL_Restart_f();
6874
6875         if (!r_drawentities.integer)
6876                 r_refdef.scene.numentities = 0;
6877         else if (r_sortentities.integer)
6878                 R_SortEntities();
6879
6880         R_AnimCache_ClearCache();
6881         R_FrameData_NewFrame();
6882
6883         /* adjust for stereo display */
6884         if(R_Stereo_Active())
6885         {
6886                 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);
6887                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6888         }
6889
6890         if (r_refdef.view.isoverlay)
6891         {
6892                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6893                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6894                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6895                 R_TimeReport("depthclear");
6896
6897                 r_refdef.view.showdebug = false;
6898
6899                 r_fb.water.enabled = false;
6900                 r_fb.water.numwaterplanes = 0;
6901
6902                 R_RenderScene(0, NULL, NULL);
6903
6904                 r_refdef.view.matrix = originalmatrix;
6905
6906                 CHECKGLERROR
6907                 return;
6908         }
6909
6910         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6911         {
6912                 r_refdef.view.matrix = originalmatrix;
6913                 return;
6914         }
6915
6916         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6917
6918         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6919                 // in sRGB fallback, behave similar to true sRGB: convert this
6920                 // value from linear to sRGB
6921                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6922
6923         R_RenderView_UpdateViewVectors();
6924
6925         R_Shadow_UpdateWorldLightSelection();
6926
6927         R_Bloom_StartFrame();
6928
6929         // apply bloom brightness offset
6930         if(r_fb.bloomtexture[0])
6931                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
6932
6933         R_Water_StartFrame();
6934
6935         // now we probably have an fbo to render into
6936         fbo = r_fb.fbo;
6937         depthtexture = r_fb.depthtexture;
6938         colortexture = r_fb.colortexture;
6939
6940         CHECKGLERROR
6941         if (r_timereport_active)
6942                 R_TimeReport("viewsetup");
6943
6944         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6945
6946         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6947         {
6948                 R_ClearScreen(r_refdef.fogenabled);
6949                 if (r_timereport_active)
6950                         R_TimeReport("viewclear");
6951         }
6952         r_refdef.view.clear = true;
6953
6954         r_refdef.view.showdebug = true;
6955
6956         R_View_Update();
6957         if (r_timereport_active)
6958                 R_TimeReport("visibility");
6959
6960         R_AnimCache_CacheVisibleEntities();
6961         if (r_timereport_active)
6962                 R_TimeReport("animcache");
6963
6964         R_Shadow_UpdateBounceGridTexture();
6965         if (r_timereport_active && r_shadow_bouncegrid.integer)
6966                 R_TimeReport("bouncegrid");
6967
6968         r_fb.water.numwaterplanes = 0;
6969         if (r_fb.water.enabled)
6970                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6971
6972         R_RenderScene(fbo, depthtexture, colortexture);
6973         r_fb.water.numwaterplanes = 0;
6974
6975         R_BlendView(fbo, depthtexture, colortexture);
6976         if (r_timereport_active)
6977                 R_TimeReport("blendview");
6978
6979         GL_Scissor(0, 0, vid.width, vid.height);
6980         GL_ScissorTest(false);
6981
6982         r_refdef.view.matrix = originalmatrix;
6983
6984         CHECKGLERROR
6985 }
6986
6987 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6988 {
6989         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6990         {
6991                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6992                 if (r_timereport_active)
6993                         R_TimeReport("waterworld");
6994         }
6995
6996         // don't let sound skip if going slow
6997         if (r_refdef.scene.extraupdate)
6998                 S_ExtraUpdate ();
6999
7000         R_DrawModelsAddWaterPlanes();
7001         if (r_timereport_active)
7002                 R_TimeReport("watermodels");
7003
7004         if (r_fb.water.numwaterplanes)
7005         {
7006                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7007                 if (r_timereport_active)
7008                         R_TimeReport("waterscenes");
7009         }
7010 }
7011
7012 extern cvar_t cl_locs_show;
7013 static void R_DrawLocs(void);
7014 static void R_DrawEntityBBoxes(void);
7015 static void R_DrawModelDecals(void);
7016 extern cvar_t cl_decals_newsystem;
7017 extern qboolean r_shadow_usingdeferredprepass;
7018 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7019 {
7020         qboolean shadowmapping = false;
7021
7022         if (r_timereport_active)
7023                 R_TimeReport("beginscene");
7024
7025         r_refdef.stats.renders++;
7026
7027         R_UpdateFog();
7028
7029         // don't let sound skip if going slow
7030         if (r_refdef.scene.extraupdate)
7031                 S_ExtraUpdate ();
7032
7033         R_MeshQueue_BeginScene();
7034
7035         R_SkyStartFrame();
7036
7037         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);
7038
7039         if (r_timereport_active)
7040                 R_TimeReport("skystartframe");
7041
7042         if (cl.csqc_vidvars.drawworld)
7043         {
7044                 // don't let sound skip if going slow
7045                 if (r_refdef.scene.extraupdate)
7046                         S_ExtraUpdate ();
7047
7048                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7049                 {
7050                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7051                         if (r_timereport_active)
7052                                 R_TimeReport("worldsky");
7053                 }
7054
7055                 if (R_DrawBrushModelsSky() && r_timereport_active)
7056                         R_TimeReport("bmodelsky");
7057
7058                 if (skyrendermasked && skyrenderlater)
7059                 {
7060                         // we have to force off the water clipping plane while rendering sky
7061                         R_SetupView(false, fbo, depthtexture, colortexture);
7062                         R_Sky();
7063                         R_SetupView(true, fbo, depthtexture, colortexture);
7064                         if (r_timereport_active)
7065                                 R_TimeReport("sky");
7066                 }
7067         }
7068
7069         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7070         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7071                 R_Shadow_PrepareModelShadows();
7072         if (r_timereport_active)
7073                 R_TimeReport("preparelights");
7074
7075         if (R_Shadow_ShadowMappingEnabled())
7076                 shadowmapping = true;
7077
7078         if (r_shadow_usingdeferredprepass)
7079                 R_Shadow_DrawPrepass();
7080
7081         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7082         {
7083                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7084                 if (r_timereport_active)
7085                         R_TimeReport("worlddepth");
7086         }
7087         if (r_depthfirst.integer >= 2)
7088         {
7089                 R_DrawModelsDepth();
7090                 if (r_timereport_active)
7091                         R_TimeReport("modeldepth");
7092         }
7093
7094         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7095         {
7096                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7097                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7098                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7099                 // don't let sound skip if going slow
7100                 if (r_refdef.scene.extraupdate)
7101                         S_ExtraUpdate ();
7102         }
7103
7104         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7105         {
7106                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7107                 if (r_timereport_active)
7108                         R_TimeReport("world");
7109         }
7110
7111         // don't let sound skip if going slow
7112         if (r_refdef.scene.extraupdate)
7113                 S_ExtraUpdate ();
7114
7115         R_DrawModels();
7116         if (r_timereport_active)
7117                 R_TimeReport("models");
7118
7119         // don't let sound skip if going slow
7120         if (r_refdef.scene.extraupdate)
7121                 S_ExtraUpdate ();
7122
7123         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7124         {
7125                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7126                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7127                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7128                 // don't let sound skip if going slow
7129                 if (r_refdef.scene.extraupdate)
7130                         S_ExtraUpdate ();
7131         }
7132
7133         if (!r_shadow_usingdeferredprepass)
7134         {
7135                 R_Shadow_DrawLights();
7136                 if (r_timereport_active)
7137                         R_TimeReport("rtlights");
7138         }
7139
7140         // don't let sound skip if going slow
7141         if (r_refdef.scene.extraupdate)
7142                 S_ExtraUpdate ();
7143
7144         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7145         {
7146                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7147                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7148                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7149                 // don't let sound skip if going slow
7150                 if (r_refdef.scene.extraupdate)
7151                         S_ExtraUpdate ();
7152         }
7153
7154         if (cl.csqc_vidvars.drawworld)
7155         {
7156                 if (cl_decals_newsystem.integer)
7157                 {
7158                         R_DrawModelDecals();
7159                         if (r_timereport_active)
7160                                 R_TimeReport("modeldecals");
7161                 }
7162                 else
7163                 {
7164                         R_DrawDecals();
7165                         if (r_timereport_active)
7166                                 R_TimeReport("decals");
7167                 }
7168
7169                 R_DrawParticles();
7170                 if (r_timereport_active)
7171                         R_TimeReport("particles");
7172
7173                 R_DrawExplosions();
7174                 if (r_timereport_active)
7175                         R_TimeReport("explosions");
7176
7177                 R_DrawLightningBeams();
7178                 if (r_timereport_active)
7179                         R_TimeReport("lightning");
7180         }
7181
7182         if (cl.csqc_loaded)
7183                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7184
7185         if (r_refdef.view.showdebug)
7186         {
7187                 if (cl_locs_show.integer)
7188                 {
7189                         R_DrawLocs();
7190                         if (r_timereport_active)
7191                                 R_TimeReport("showlocs");
7192                 }
7193
7194                 if (r_drawportals.integer)
7195                 {
7196                         R_DrawPortals();
7197                         if (r_timereport_active)
7198                                 R_TimeReport("portals");
7199                 }
7200
7201                 if (r_showbboxes.value > 0)
7202                 {
7203                         R_DrawEntityBBoxes();
7204                         if (r_timereport_active)
7205                                 R_TimeReport("bboxes");
7206                 }
7207         }
7208
7209         if (r_transparent.integer)
7210         {
7211                 R_MeshQueue_RenderTransparent();
7212                 if (r_timereport_active)
7213                         R_TimeReport("drawtrans");
7214         }
7215
7216         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))
7217         {
7218                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7219                 if (r_timereport_active)
7220                         R_TimeReport("worlddebug");
7221                 R_DrawModelsDebug();
7222                 if (r_timereport_active)
7223                         R_TimeReport("modeldebug");
7224         }
7225
7226         if (cl.csqc_vidvars.drawworld)
7227         {
7228                 R_Shadow_DrawCoronas();
7229                 if (r_timereport_active)
7230                         R_TimeReport("coronas");
7231         }
7232
7233 #if 0
7234         {
7235                 GL_DepthTest(false);
7236                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7237                 GL_Color(1, 1, 1, 1);
7238                 qglBegin(GL_POLYGON);
7239                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7240                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7241                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7242                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7243                 qglEnd();
7244                 qglBegin(GL_POLYGON);
7245                 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]);
7246                 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]);
7247                 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]);
7248                 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]);
7249                 qglEnd();
7250                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7251         }
7252 #endif
7253
7254         // don't let sound skip if going slow
7255         if (r_refdef.scene.extraupdate)
7256                 S_ExtraUpdate ();
7257 }
7258
7259 static const unsigned short bboxelements[36] =
7260 {
7261         5, 1, 3, 5, 3, 7,
7262         6, 2, 0, 6, 0, 4,
7263         7, 3, 2, 7, 2, 6,
7264         4, 0, 1, 4, 1, 5,
7265         4, 5, 7, 4, 7, 6,
7266         1, 0, 2, 1, 2, 3,
7267 };
7268
7269 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7270 {
7271         int i;
7272         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7273
7274         RSurf_ActiveWorldEntity();
7275
7276         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7277         GL_DepthMask(false);
7278         GL_DepthRange(0, 1);
7279         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7280 //      R_Mesh_ResetTextureState();
7281
7282         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7283         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7284         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7285         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7286         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7287         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7288         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7289         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7290         R_FillColors(color4f, 8, cr, cg, cb, ca);
7291         if (r_refdef.fogenabled)
7292         {
7293                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7294                 {
7295                         f1 = RSurf_FogVertex(v);
7296                         f2 = 1 - f1;
7297                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7298                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7299                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7300                 }
7301         }
7302         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7303         R_Mesh_ResetTextureState();
7304         R_SetupShader_Generic_NoTexture(false, false);
7305         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7306 }
7307
7308 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7309 {
7310         prvm_prog_t *prog = SVVM_prog;
7311         int i;
7312         float color[4];
7313         prvm_edict_t *edict;
7314
7315         // this function draws bounding boxes of server entities
7316         if (!sv.active)
7317                 return;
7318
7319         GL_CullFace(GL_NONE);
7320         R_SetupShader_Generic_NoTexture(false, false);
7321
7322         for (i = 0;i < numsurfaces;i++)
7323         {
7324                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7325                 switch ((int)PRVM_serveredictfloat(edict, solid))
7326                 {
7327                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7328                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7329                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7330                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7331                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7332                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7333                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7334                 }
7335                 color[3] *= r_showbboxes.value;
7336                 color[3] = bound(0, color[3], 1);
7337                 GL_DepthTest(!r_showdisabledepthtest.integer);
7338                 GL_CullFace(r_refdef.view.cullface_front);
7339                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7340         }
7341 }
7342
7343 static void R_DrawEntityBBoxes(void)
7344 {
7345         int i;
7346         prvm_edict_t *edict;
7347         vec3_t center;
7348         prvm_prog_t *prog = SVVM_prog;
7349
7350         // this function draws bounding boxes of server entities
7351         if (!sv.active)
7352                 return;
7353
7354         for (i = 0;i < prog->num_edicts;i++)
7355         {
7356                 edict = PRVM_EDICT_NUM(i);
7357                 if (edict->priv.server->free)
7358                         continue;
7359                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7360                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7361                         continue;
7362                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7363                         continue;
7364                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7365                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7366         }
7367 }
7368
7369 static const int nomodelelement3i[24] =
7370 {
7371         5, 2, 0,
7372         5, 1, 2,
7373         5, 0, 3,
7374         5, 3, 1,
7375         0, 2, 4,
7376         2, 1, 4,
7377         3, 0, 4,
7378         1, 3, 4
7379 };
7380
7381 static const unsigned short nomodelelement3s[24] =
7382 {
7383         5, 2, 0,
7384         5, 1, 2,
7385         5, 0, 3,
7386         5, 3, 1,
7387         0, 2, 4,
7388         2, 1, 4,
7389         3, 0, 4,
7390         1, 3, 4
7391 };
7392
7393 static const float nomodelvertex3f[6*3] =
7394 {
7395         -16,   0,   0,
7396          16,   0,   0,
7397           0, -16,   0,
7398           0,  16,   0,
7399           0,   0, -16,
7400           0,   0,  16
7401 };
7402
7403 static const float nomodelcolor4f[6*4] =
7404 {
7405         0.0f, 0.0f, 0.5f, 1.0f,
7406         0.0f, 0.0f, 0.5f, 1.0f,
7407         0.0f, 0.5f, 0.0f, 1.0f,
7408         0.0f, 0.5f, 0.0f, 1.0f,
7409         0.5f, 0.0f, 0.0f, 1.0f,
7410         0.5f, 0.0f, 0.0f, 1.0f
7411 };
7412
7413 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7414 {
7415         int i;
7416         float f1, f2, *c;
7417         float color4f[6*4];
7418
7419         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);
7420
7421         // this is only called once per entity so numsurfaces is always 1, and
7422         // surfacelist is always {0}, so this code does not handle batches
7423
7424         if (rsurface.ent_flags & RENDER_ADDITIVE)
7425         {
7426                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7427                 GL_DepthMask(false);
7428         }
7429         else if (rsurface.colormod[3] < 1)
7430         {
7431                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7432                 GL_DepthMask(false);
7433         }
7434         else
7435         {
7436                 GL_BlendFunc(GL_ONE, GL_ZERO);
7437                 GL_DepthMask(true);
7438         }
7439         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7440         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7441         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7442         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7443         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7444         for (i = 0, c = color4f;i < 6;i++, c += 4)
7445         {
7446                 c[0] *= rsurface.colormod[0];
7447                 c[1] *= rsurface.colormod[1];
7448                 c[2] *= rsurface.colormod[2];
7449                 c[3] *= rsurface.colormod[3];
7450         }
7451         if (r_refdef.fogenabled)
7452         {
7453                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7454                 {
7455                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7456                         f2 = 1 - f1;
7457                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7458                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7459                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7460                 }
7461         }
7462 //      R_Mesh_ResetTextureState();
7463         R_SetupShader_Generic_NoTexture(false, false);
7464         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7465         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7466 }
7467
7468 void R_DrawNoModel(entity_render_t *ent)
7469 {
7470         vec3_t org;
7471         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7472         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7473                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7474         else
7475                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7476 }
7477
7478 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7479 {
7480         vec3_t right1, right2, diff, normal;
7481
7482         VectorSubtract (org2, org1, normal);
7483
7484         // calculate 'right' vector for start
7485         VectorSubtract (r_refdef.view.origin, org1, diff);
7486         CrossProduct (normal, diff, right1);
7487         VectorNormalize (right1);
7488
7489         // calculate 'right' vector for end
7490         VectorSubtract (r_refdef.view.origin, org2, diff);
7491         CrossProduct (normal, diff, right2);
7492         VectorNormalize (right2);
7493
7494         vert[ 0] = org1[0] + width * right1[0];
7495         vert[ 1] = org1[1] + width * right1[1];
7496         vert[ 2] = org1[2] + width * right1[2];
7497         vert[ 3] = org1[0] - width * right1[0];
7498         vert[ 4] = org1[1] - width * right1[1];
7499         vert[ 5] = org1[2] - width * right1[2];
7500         vert[ 6] = org2[0] - width * right2[0];
7501         vert[ 7] = org2[1] - width * right2[1];
7502         vert[ 8] = org2[2] - width * right2[2];
7503         vert[ 9] = org2[0] + width * right2[0];
7504         vert[10] = org2[1] + width * right2[1];
7505         vert[11] = org2[2] + width * right2[2];
7506 }
7507
7508 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)
7509 {
7510         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7511         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7512         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7513         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7514         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7515         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7516         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7517         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7518         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7519         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7520         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7521         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7522 }
7523
7524 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7525 {
7526         int i;
7527         float *vertex3f;
7528         float v[3];
7529         VectorSet(v, x, y, z);
7530         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7531                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7532                         break;
7533         if (i == mesh->numvertices)
7534         {
7535                 if (mesh->numvertices < mesh->maxvertices)
7536                 {
7537                         VectorCopy(v, vertex3f);
7538                         mesh->numvertices++;
7539                 }
7540                 return mesh->numvertices;
7541         }
7542         else
7543                 return i;
7544 }
7545
7546 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7547 {
7548         int i;
7549         int *e, element[3];
7550         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7551         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7552         e = mesh->element3i + mesh->numtriangles * 3;
7553         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7554         {
7555                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7556                 if (mesh->numtriangles < mesh->maxtriangles)
7557                 {
7558                         *e++ = element[0];
7559                         *e++ = element[1];
7560                         *e++ = element[2];
7561                         mesh->numtriangles++;
7562                 }
7563                 element[1] = element[2];
7564         }
7565 }
7566
7567 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7568 {
7569         int i;
7570         int *e, element[3];
7571         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7572         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7573         e = mesh->element3i + mesh->numtriangles * 3;
7574         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7575         {
7576                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7577                 if (mesh->numtriangles < mesh->maxtriangles)
7578                 {
7579                         *e++ = element[0];
7580                         *e++ = element[1];
7581                         *e++ = element[2];
7582                         mesh->numtriangles++;
7583                 }
7584                 element[1] = element[2];
7585         }
7586 }
7587
7588 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7589 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7590 {
7591         int planenum, planenum2;
7592         int w;
7593         int tempnumpoints;
7594         mplane_t *plane, *plane2;
7595         double maxdist;
7596         double temppoints[2][256*3];
7597         // figure out how large a bounding box we need to properly compute this brush
7598         maxdist = 0;
7599         for (w = 0;w < numplanes;w++)
7600                 maxdist = max(maxdist, fabs(planes[w].dist));
7601         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7602         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7603         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7604         {
7605                 w = 0;
7606                 tempnumpoints = 4;
7607                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7608                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7609                 {
7610                         if (planenum2 == planenum)
7611                                 continue;
7612                         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);
7613                         w = !w;
7614                 }
7615                 if (tempnumpoints < 3)
7616                         continue;
7617                 // generate elements forming a triangle fan for this polygon
7618                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7619         }
7620 }
7621
7622 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)
7623 {
7624         texturelayer_t *layer;
7625         layer = t->currentlayers + t->currentnumlayers++;
7626         layer->type = type;
7627         layer->depthmask = depthmask;
7628         layer->blendfunc1 = blendfunc1;
7629         layer->blendfunc2 = blendfunc2;
7630         layer->texture = texture;
7631         layer->texmatrix = *matrix;
7632         layer->color[0] = r;
7633         layer->color[1] = g;
7634         layer->color[2] = b;
7635         layer->color[3] = a;
7636 }
7637
7638 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7639 {
7640         if(parms[0] == 0 && parms[1] == 0)
7641                 return false;
7642         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7643                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7644                         return false;
7645         return true;
7646 }
7647
7648 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7649 {
7650         double index, f;
7651         index = parms[2] + rsurface.shadertime * parms[3];
7652         index -= floor(index);
7653         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7654         {
7655         default:
7656         case Q3WAVEFUNC_NONE:
7657         case Q3WAVEFUNC_NOISE:
7658         case Q3WAVEFUNC_COUNT:
7659                 f = 0;
7660                 break;
7661         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7662         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7663         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7664         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7665         case Q3WAVEFUNC_TRIANGLE:
7666                 index *= 4;
7667                 f = index - floor(index);
7668                 if (index < 1)
7669                 {
7670                         // f = f;
7671                 }
7672                 else if (index < 2)
7673                         f = 1 - f;
7674                 else if (index < 3)
7675                         f = -f;
7676                 else
7677                         f = -(1 - f);
7678                 break;
7679         }
7680         f = parms[0] + parms[1] * f;
7681         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7682                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7683         return (float) f;
7684 }
7685
7686 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7687 {
7688         int w, h, idx;
7689         double f;
7690         double offsetd[2];
7691         float tcmat[12];
7692         matrix4x4_t matrix, temp;
7693         switch(tcmod->tcmod)
7694         {
7695                 case Q3TCMOD_COUNT:
7696                 case Q3TCMOD_NONE:
7697                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7698                                 matrix = r_waterscrollmatrix;
7699                         else
7700                                 matrix = identitymatrix;
7701                         break;
7702                 case Q3TCMOD_ENTITYTRANSLATE:
7703                         // this is used in Q3 to allow the gamecode to control texcoord
7704                         // scrolling on the entity, which is not supported in darkplaces yet.
7705                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7706                         break;
7707                 case Q3TCMOD_ROTATE:
7708                         f = tcmod->parms[0] * rsurface.shadertime;
7709                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7710                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7711                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7712                         break;
7713                 case Q3TCMOD_SCALE:
7714                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7715                         break;
7716                 case Q3TCMOD_SCROLL:
7717                         // extra care is needed because of precision breakdown with large values of time
7718                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7719                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7720                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7721                         break;
7722                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7723                         w = (int) tcmod->parms[0];
7724                         h = (int) tcmod->parms[1];
7725                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7726                         f = f - floor(f);
7727                         idx = (int) floor(f * w * h);
7728                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7729                         break;
7730                 case Q3TCMOD_STRETCH:
7731                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7732                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7733                         break;
7734                 case Q3TCMOD_TRANSFORM:
7735                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7736                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7737                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7738                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7739                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7740                         break;
7741                 case Q3TCMOD_TURBULENT:
7742                         // this is handled in the RSurf_PrepareVertices function
7743                         matrix = identitymatrix;
7744                         break;
7745         }
7746         temp = *texmatrix;
7747         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7748 }
7749
7750 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7751 {
7752         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7753         char name[MAX_QPATH];
7754         skinframe_t *skinframe;
7755         unsigned char pixels[296*194];
7756         strlcpy(cache->name, skinname, sizeof(cache->name));
7757         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7758         if (developer_loading.integer)
7759                 Con_Printf("loading %s\n", name);
7760         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7761         if (!skinframe || !skinframe->base)
7762         {
7763                 unsigned char *f;
7764                 fs_offset_t filesize;
7765                 skinframe = NULL;
7766                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7767                 if (f)
7768                 {
7769                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7770                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7771                         Mem_Free(f);
7772                 }
7773         }
7774         cache->skinframe = skinframe;
7775 }
7776
7777 texture_t *R_GetCurrentTexture(texture_t *t)
7778 {
7779         int i;
7780         const entity_render_t *ent = rsurface.entity;
7781         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7782         q3shaderinfo_layer_tcmod_t *tcmod;
7783
7784         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7785                 return t->currentframe;
7786         t->update_lastrenderframe = r_textureframe;
7787         t->update_lastrenderentity = (void *)ent;
7788
7789         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7790                 t->camera_entity = ent->entitynumber;
7791         else
7792                 t->camera_entity = 0;
7793
7794         // switch to an alternate material if this is a q1bsp animated material
7795         {
7796                 texture_t *texture = t;
7797                 int s = rsurface.ent_skinnum;
7798                 if ((unsigned int)s >= (unsigned int)model->numskins)
7799                         s = 0;
7800                 if (model->skinscenes)
7801                 {
7802                         if (model->skinscenes[s].framecount > 1)
7803                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7804                         else
7805                                 s = model->skinscenes[s].firstframe;
7806                 }
7807                 if (s > 0)
7808                         t = t + s * model->num_surfaces;
7809                 if (t->animated)
7810                 {
7811                         // use an alternate animation if the entity's frame is not 0,
7812                         // and only if the texture has an alternate animation
7813                         if (rsurface.ent_alttextures && t->anim_total[1])
7814                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7815                         else
7816                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7817                 }
7818                 texture->currentframe = t;
7819         }
7820
7821         // update currentskinframe to be a qw skin or animation frame
7822         if (rsurface.ent_qwskin >= 0)
7823         {
7824                 i = rsurface.ent_qwskin;
7825                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7826                 {
7827                         r_qwskincache_size = cl.maxclients;
7828                         if (r_qwskincache)
7829                                 Mem_Free(r_qwskincache);
7830                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7831                 }
7832                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7833                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7834                 t->currentskinframe = r_qwskincache[i].skinframe;
7835                 if (t->currentskinframe == NULL)
7836                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7837         }
7838         else if (t->numskinframes >= 2)
7839                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7840         if (t->backgroundnumskinframes >= 2)
7841                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7842
7843         t->currentmaterialflags = t->basematerialflags;
7844         t->currentalpha = rsurface.colormod[3];
7845         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7846                 t->currentalpha *= r_wateralpha.value;
7847         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7848                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7849         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7850                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7851         if (!(rsurface.ent_flags & RENDER_LIGHT))
7852                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7853         else if (FAKELIGHT_ENABLED)
7854         {
7855                 // no modellight if using fakelight for the map
7856         }
7857         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7858         {
7859                 // pick a model lighting mode
7860                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7861                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7862                 else
7863                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7864         }
7865         if (rsurface.ent_flags & RENDER_ADDITIVE)
7866                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7867         else if (t->currentalpha < 1)
7868                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7869         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7870         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7871                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7872         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7873                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7874         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7875                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7876         if (t->backgroundnumskinframes)
7877                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7878         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7879         {
7880                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7881                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7882         }
7883         else
7884                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7885         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7886         {
7887                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7888                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7889         }
7890         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7891                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7892
7893         // there is no tcmod
7894         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7895         {
7896                 t->currenttexmatrix = r_waterscrollmatrix;
7897                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7898         }
7899         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7900         {
7901                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7902                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7903         }
7904
7905         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7906                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7907         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7908                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7909
7910         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7911         if (t->currentskinframe->qpixels)
7912                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7913         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7914         if (!t->basetexture)
7915                 t->basetexture = r_texture_notexture;
7916         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7917         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7918         t->nmaptexture = t->currentskinframe->nmap;
7919         if (!t->nmaptexture)
7920                 t->nmaptexture = r_texture_blanknormalmap;
7921         t->glosstexture = r_texture_black;
7922         t->glowtexture = t->currentskinframe->glow;
7923         t->fogtexture = t->currentskinframe->fog;
7924         t->reflectmasktexture = t->currentskinframe->reflect;
7925         if (t->backgroundnumskinframes)
7926         {
7927                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7928                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7929                 t->backgroundglosstexture = r_texture_black;
7930                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7931                 if (!t->backgroundnmaptexture)
7932                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7933                 // make sure that if glow is going to be used, both textures are not NULL
7934                 if (!t->backgroundglowtexture && t->glowtexture)
7935                         t->backgroundglowtexture = r_texture_black;
7936                 if (!t->glowtexture && t->backgroundglowtexture)
7937                         t->glowtexture = r_texture_black;
7938         }
7939         else
7940         {
7941                 t->backgroundbasetexture = r_texture_white;
7942                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7943                 t->backgroundglosstexture = r_texture_black;
7944                 t->backgroundglowtexture = NULL;
7945         }
7946         t->specularpower = r_shadow_glossexponent.value;
7947         // TODO: store reference values for these in the texture?
7948         t->specularscale = 0;
7949         if (r_shadow_gloss.integer > 0)
7950         {
7951                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7952                 {
7953                         if (r_shadow_glossintensity.value > 0)
7954                         {
7955                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7956                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7957                                 t->specularscale = r_shadow_glossintensity.value;
7958                         }
7959                 }
7960                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7961                 {
7962                         t->glosstexture = r_texture_white;
7963                         t->backgroundglosstexture = r_texture_white;
7964                         t->specularscale = r_shadow_gloss2intensity.value;
7965                         t->specularpower = r_shadow_gloss2exponent.value;
7966                 }
7967         }
7968         t->specularscale *= t->specularscalemod;
7969         t->specularpower *= t->specularpowermod;
7970         t->rtlightambient = 0;
7971
7972         // lightmaps mode looks bad with dlights using actual texturing, so turn
7973         // off the colormap and glossmap, but leave the normalmap on as it still
7974         // accurately represents the shading involved
7975         if (gl_lightmaps.integer)
7976         {
7977                 t->basetexture = r_texture_grey128;
7978                 t->pantstexture = r_texture_black;
7979                 t->shirttexture = r_texture_black;
7980                 if (gl_lightmaps.integer < 2)
7981                         t->nmaptexture = r_texture_blanknormalmap;
7982                 t->glosstexture = r_texture_black;
7983                 t->glowtexture = NULL;
7984                 t->fogtexture = NULL;
7985                 t->reflectmasktexture = NULL;
7986                 t->backgroundbasetexture = NULL;
7987                 if (gl_lightmaps.integer < 2)
7988                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7989                 t->backgroundglosstexture = r_texture_black;
7990                 t->backgroundglowtexture = NULL;
7991                 t->specularscale = 0;
7992                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7993         }
7994
7995         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7996         VectorClear(t->dlightcolor);
7997         t->currentnumlayers = 0;
7998         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7999         {
8000                 int blendfunc1, blendfunc2;
8001                 qboolean depthmask;
8002                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8003                 {
8004                         blendfunc1 = GL_SRC_ALPHA;
8005                         blendfunc2 = GL_ONE;
8006                 }
8007                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8008                 {
8009                         blendfunc1 = GL_SRC_ALPHA;
8010                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8011                 }
8012                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8013                 {
8014                         blendfunc1 = t->customblendfunc[0];
8015                         blendfunc2 = t->customblendfunc[1];
8016                 }
8017                 else
8018                 {
8019                         blendfunc1 = GL_ONE;
8020                         blendfunc2 = GL_ZERO;
8021                 }
8022                 // don't colormod evilblend textures
8023                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8024                         VectorSet(t->lightmapcolor, 1, 1, 1);
8025                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8026                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8027                 {
8028                         // fullbright is not affected by r_refdef.lightmapintensity
8029                         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]);
8030                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8031                                 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]);
8032                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8033                                 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]);
8034                 }
8035                 else
8036                 {
8037                         vec3_t ambientcolor;
8038                         float colorscale;
8039                         // set the color tint used for lights affecting this surface
8040                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8041                         colorscale = 2;
8042                         // q3bsp has no lightmap updates, so the lightstylevalue that
8043                         // would normally be baked into the lightmap must be
8044                         // applied to the color
8045                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8046                         if (model->type == mod_brushq3)
8047                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8048                         colorscale *= r_refdef.lightmapintensity;
8049                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8050                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8051                         // basic lit geometry
8052                         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]);
8053                         // add pants/shirt if needed
8054                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8055                                 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]);
8056                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8057                                 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]);
8058                         // now add ambient passes if needed
8059                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8060                         {
8061                                 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]);
8062                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8063                                         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]);
8064                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8065                                         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]);
8066                         }
8067                 }
8068                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8069                         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]);
8070                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8071                 {
8072                         // if this is opaque use alpha blend which will darken the earlier
8073                         // passes cheaply.
8074                         //
8075                         // if this is an alpha blended material, all the earlier passes
8076                         // were darkened by fog already, so we only need to add the fog
8077                         // color ontop through the fog mask texture
8078                         //
8079                         // if this is an additive blended material, all the earlier passes
8080                         // were darkened by fog already, and we should not add fog color
8081                         // (because the background was not darkened, there is no fog color
8082                         // that was lost behind it).
8083                         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]);
8084                 }
8085         }
8086
8087         return t->currentframe;
8088 }
8089
8090 rsurfacestate_t rsurface;
8091
8092 void RSurf_ActiveWorldEntity(void)
8093 {
8094         dp_model_t *model = r_refdef.scene.worldmodel;
8095         //if (rsurface.entity == r_refdef.scene.worldentity)
8096         //      return;
8097         rsurface.entity = r_refdef.scene.worldentity;
8098         rsurface.skeleton = NULL;
8099         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8100         rsurface.ent_skinnum = 0;
8101         rsurface.ent_qwskin = -1;
8102         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8103         rsurface.shadertime = r_refdef.scene.time;
8104         rsurface.matrix = identitymatrix;
8105         rsurface.inversematrix = identitymatrix;
8106         rsurface.matrixscale = 1;
8107         rsurface.inversematrixscale = 1;
8108         R_EntityMatrix(&identitymatrix);
8109         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8110         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8111         rsurface.fograngerecip = r_refdef.fograngerecip;
8112         rsurface.fogheightfade = r_refdef.fogheightfade;
8113         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8114         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8115         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8116         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8117         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8118         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8119         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8120         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8121         rsurface.colormod[3] = 1;
8122         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);
8123         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8124         rsurface.frameblend[0].lerp = 1;
8125         rsurface.ent_alttextures = false;
8126         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8127         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8128         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8129         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8130         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8131         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8132         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8133         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8134         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8135         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8136         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8137         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8138         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8139         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8140         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8141         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8142         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8143         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8144         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8145         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8146         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8147         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8148         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8149         rsurface.modelelement3i = model->surfmesh.data_element3i;
8150         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8151         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8152         rsurface.modelelement3s = model->surfmesh.data_element3s;
8153         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8154         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8155         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8156         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8157         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8158         rsurface.modelsurfaces = model->data_surfaces;
8159         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8160         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8161         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8162         rsurface.modelgeneratedvertex = false;
8163         rsurface.batchgeneratedvertex = false;
8164         rsurface.batchfirstvertex = 0;
8165         rsurface.batchnumvertices = 0;
8166         rsurface.batchfirsttriangle = 0;
8167         rsurface.batchnumtriangles = 0;
8168         rsurface.batchvertex3f  = NULL;
8169         rsurface.batchvertex3f_vertexbuffer = NULL;
8170         rsurface.batchvertex3f_bufferoffset = 0;
8171         rsurface.batchsvector3f = NULL;
8172         rsurface.batchsvector3f_vertexbuffer = NULL;
8173         rsurface.batchsvector3f_bufferoffset = 0;
8174         rsurface.batchtvector3f = NULL;
8175         rsurface.batchtvector3f_vertexbuffer = NULL;
8176         rsurface.batchtvector3f_bufferoffset = 0;
8177         rsurface.batchnormal3f  = NULL;
8178         rsurface.batchnormal3f_vertexbuffer = NULL;
8179         rsurface.batchnormal3f_bufferoffset = 0;
8180         rsurface.batchlightmapcolor4f = NULL;
8181         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8182         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8183         rsurface.batchtexcoordtexture2f = NULL;
8184         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8185         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8186         rsurface.batchtexcoordlightmap2f = NULL;
8187         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8188         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8189         rsurface.batchvertexmesh = NULL;
8190         rsurface.batchvertexmeshbuffer = NULL;
8191         rsurface.batchvertex3fbuffer = NULL;
8192         rsurface.batchelement3i = NULL;
8193         rsurface.batchelement3i_indexbuffer = NULL;
8194         rsurface.batchelement3i_bufferoffset = 0;
8195         rsurface.batchelement3s = NULL;
8196         rsurface.batchelement3s_indexbuffer = NULL;
8197         rsurface.batchelement3s_bufferoffset = 0;
8198         rsurface.passcolor4f = NULL;
8199         rsurface.passcolor4f_vertexbuffer = NULL;
8200         rsurface.passcolor4f_bufferoffset = 0;
8201         rsurface.forcecurrenttextureupdate = false;
8202 }
8203
8204 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8205 {
8206         dp_model_t *model = ent->model;
8207         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8208         //      return;
8209         rsurface.entity = (entity_render_t *)ent;
8210         rsurface.skeleton = ent->skeleton;
8211         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8212         rsurface.ent_skinnum = ent->skinnum;
8213         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;
8214         rsurface.ent_flags = ent->flags;
8215         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8216         rsurface.matrix = ent->matrix;
8217         rsurface.inversematrix = ent->inversematrix;
8218         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8219         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8220         R_EntityMatrix(&rsurface.matrix);
8221         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8222         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8223         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8224         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8225         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8226         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8227         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8228         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8229         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8230         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8231         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8232         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8233         rsurface.colormod[3] = ent->alpha;
8234         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8235         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8236         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8237         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8238         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8239         if (ent->model->brush.submodel && !prepass)
8240         {
8241                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8242                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8243         }
8244         if (model->surfmesh.isanimated && model->AnimateVertices)
8245         {
8246                 if (ent->animcache_vertex3f)
8247                 {
8248                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8249                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8250                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8251                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8252                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8253                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8254                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8255                 }
8256                 else if (wanttangents)
8257                 {
8258                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8259                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8260                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8261                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8262                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8263                         rsurface.modelvertexmesh = NULL;
8264                         rsurface.modelvertexmeshbuffer = NULL;
8265                         rsurface.modelvertex3fbuffer = NULL;
8266                 }
8267                 else if (wantnormals)
8268                 {
8269                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8270                         rsurface.modelsvector3f = NULL;
8271                         rsurface.modeltvector3f = NULL;
8272                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8273                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8274                         rsurface.modelvertexmesh = NULL;
8275                         rsurface.modelvertexmeshbuffer = NULL;
8276                         rsurface.modelvertex3fbuffer = NULL;
8277                 }
8278                 else
8279                 {
8280                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8281                         rsurface.modelsvector3f = NULL;
8282                         rsurface.modeltvector3f = NULL;
8283                         rsurface.modelnormal3f = NULL;
8284                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8285                         rsurface.modelvertexmesh = NULL;
8286                         rsurface.modelvertexmeshbuffer = NULL;
8287                         rsurface.modelvertex3fbuffer = NULL;
8288                 }
8289                 rsurface.modelvertex3f_vertexbuffer = 0;
8290                 rsurface.modelvertex3f_bufferoffset = 0;
8291                 rsurface.modelsvector3f_vertexbuffer = 0;
8292                 rsurface.modelsvector3f_bufferoffset = 0;
8293                 rsurface.modeltvector3f_vertexbuffer = 0;
8294                 rsurface.modeltvector3f_bufferoffset = 0;
8295                 rsurface.modelnormal3f_vertexbuffer = 0;
8296                 rsurface.modelnormal3f_bufferoffset = 0;
8297                 rsurface.modelgeneratedvertex = true;
8298         }
8299         else
8300         {
8301                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8302                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8303                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8304                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8305                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8306                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8307                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8308                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8309                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8310                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8311                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8312                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8313                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8314                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8315                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8316                 rsurface.modelgeneratedvertex = false;
8317         }
8318         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8319         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8320         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8321         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8322         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8323         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8324         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8325         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8326         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8327         rsurface.modelelement3i = model->surfmesh.data_element3i;
8328         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8329         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8330         rsurface.modelelement3s = model->surfmesh.data_element3s;
8331         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8332         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8333         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8334         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8335         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8336         rsurface.modelsurfaces = model->data_surfaces;
8337         rsurface.batchgeneratedvertex = false;
8338         rsurface.batchfirstvertex = 0;
8339         rsurface.batchnumvertices = 0;
8340         rsurface.batchfirsttriangle = 0;
8341         rsurface.batchnumtriangles = 0;
8342         rsurface.batchvertex3f  = NULL;
8343         rsurface.batchvertex3f_vertexbuffer = NULL;
8344         rsurface.batchvertex3f_bufferoffset = 0;
8345         rsurface.batchsvector3f = NULL;
8346         rsurface.batchsvector3f_vertexbuffer = NULL;
8347         rsurface.batchsvector3f_bufferoffset = 0;
8348         rsurface.batchtvector3f = NULL;
8349         rsurface.batchtvector3f_vertexbuffer = NULL;
8350         rsurface.batchtvector3f_bufferoffset = 0;
8351         rsurface.batchnormal3f  = NULL;
8352         rsurface.batchnormal3f_vertexbuffer = NULL;
8353         rsurface.batchnormal3f_bufferoffset = 0;
8354         rsurface.batchlightmapcolor4f = NULL;
8355         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8356         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8357         rsurface.batchtexcoordtexture2f = NULL;
8358         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8359         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8360         rsurface.batchtexcoordlightmap2f = NULL;
8361         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8362         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8363         rsurface.batchvertexmesh = NULL;
8364         rsurface.batchvertexmeshbuffer = NULL;
8365         rsurface.batchvertex3fbuffer = NULL;
8366         rsurface.batchelement3i = NULL;
8367         rsurface.batchelement3i_indexbuffer = NULL;
8368         rsurface.batchelement3i_bufferoffset = 0;
8369         rsurface.batchelement3s = NULL;
8370         rsurface.batchelement3s_indexbuffer = NULL;
8371         rsurface.batchelement3s_bufferoffset = 0;
8372         rsurface.passcolor4f = NULL;
8373         rsurface.passcolor4f_vertexbuffer = NULL;
8374         rsurface.passcolor4f_bufferoffset = 0;
8375         rsurface.forcecurrenttextureupdate = false;
8376 }
8377
8378 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)
8379 {
8380         rsurface.entity = r_refdef.scene.worldentity;
8381         rsurface.skeleton = NULL;
8382         rsurface.ent_skinnum = 0;
8383         rsurface.ent_qwskin = -1;
8384         rsurface.ent_flags = entflags;
8385         rsurface.shadertime = r_refdef.scene.time - shadertime;
8386         rsurface.modelnumvertices = numvertices;
8387         rsurface.modelnumtriangles = numtriangles;
8388         rsurface.matrix = *matrix;
8389         rsurface.inversematrix = *inversematrix;
8390         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8391         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8392         R_EntityMatrix(&rsurface.matrix);
8393         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8394         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8395         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8396         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8397         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8398         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8399         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8400         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8401         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8402         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8403         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8404         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8405         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);
8406         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8407         rsurface.frameblend[0].lerp = 1;
8408         rsurface.ent_alttextures = false;
8409         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8410         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8411         if (wanttangents)
8412         {
8413                 rsurface.modelvertex3f = (float *)vertex3f;
8414                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8415                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8416                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8417         }
8418         else if (wantnormals)
8419         {
8420                 rsurface.modelvertex3f = (float *)vertex3f;
8421                 rsurface.modelsvector3f = NULL;
8422                 rsurface.modeltvector3f = NULL;
8423                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8424         }
8425         else
8426         {
8427                 rsurface.modelvertex3f = (float *)vertex3f;
8428                 rsurface.modelsvector3f = NULL;
8429                 rsurface.modeltvector3f = NULL;
8430                 rsurface.modelnormal3f = NULL;
8431         }
8432         rsurface.modelvertexmesh = NULL;
8433         rsurface.modelvertexmeshbuffer = NULL;
8434         rsurface.modelvertex3fbuffer = NULL;
8435         rsurface.modelvertex3f_vertexbuffer = 0;
8436         rsurface.modelvertex3f_bufferoffset = 0;
8437         rsurface.modelsvector3f_vertexbuffer = 0;
8438         rsurface.modelsvector3f_bufferoffset = 0;
8439         rsurface.modeltvector3f_vertexbuffer = 0;
8440         rsurface.modeltvector3f_bufferoffset = 0;
8441         rsurface.modelnormal3f_vertexbuffer = 0;
8442         rsurface.modelnormal3f_bufferoffset = 0;
8443         rsurface.modelgeneratedvertex = true;
8444         rsurface.modellightmapcolor4f  = (float *)color4f;
8445         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8446         rsurface.modellightmapcolor4f_bufferoffset = 0;
8447         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8448         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8449         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8450         rsurface.modeltexcoordlightmap2f  = NULL;
8451         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8452         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8453         rsurface.modelelement3i = (int *)element3i;
8454         rsurface.modelelement3i_indexbuffer = NULL;
8455         rsurface.modelelement3i_bufferoffset = 0;
8456         rsurface.modelelement3s = (unsigned short *)element3s;
8457         rsurface.modelelement3s_indexbuffer = NULL;
8458         rsurface.modelelement3s_bufferoffset = 0;
8459         rsurface.modellightmapoffsets = NULL;
8460         rsurface.modelsurfaces = NULL;
8461         rsurface.batchgeneratedvertex = false;
8462         rsurface.batchfirstvertex = 0;
8463         rsurface.batchnumvertices = 0;
8464         rsurface.batchfirsttriangle = 0;
8465         rsurface.batchnumtriangles = 0;
8466         rsurface.batchvertex3f  = NULL;
8467         rsurface.batchvertex3f_vertexbuffer = NULL;
8468         rsurface.batchvertex3f_bufferoffset = 0;
8469         rsurface.batchsvector3f = NULL;
8470         rsurface.batchsvector3f_vertexbuffer = NULL;
8471         rsurface.batchsvector3f_bufferoffset = 0;
8472         rsurface.batchtvector3f = NULL;
8473         rsurface.batchtvector3f_vertexbuffer = NULL;
8474         rsurface.batchtvector3f_bufferoffset = 0;
8475         rsurface.batchnormal3f  = NULL;
8476         rsurface.batchnormal3f_vertexbuffer = NULL;
8477         rsurface.batchnormal3f_bufferoffset = 0;
8478         rsurface.batchlightmapcolor4f = NULL;
8479         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8480         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8481         rsurface.batchtexcoordtexture2f = NULL;
8482         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8483         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8484         rsurface.batchtexcoordlightmap2f = NULL;
8485         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8486         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8487         rsurface.batchvertexmesh = NULL;
8488         rsurface.batchvertexmeshbuffer = NULL;
8489         rsurface.batchvertex3fbuffer = NULL;
8490         rsurface.batchelement3i = NULL;
8491         rsurface.batchelement3i_indexbuffer = NULL;
8492         rsurface.batchelement3i_bufferoffset = 0;
8493         rsurface.batchelement3s = NULL;
8494         rsurface.batchelement3s_indexbuffer = NULL;
8495         rsurface.batchelement3s_bufferoffset = 0;
8496         rsurface.passcolor4f = NULL;
8497         rsurface.passcolor4f_vertexbuffer = NULL;
8498         rsurface.passcolor4f_bufferoffset = 0;
8499         rsurface.forcecurrenttextureupdate = true;
8500
8501         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8502         {
8503                 if ((wantnormals || wanttangents) && !normal3f)
8504                 {
8505                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8506                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8507                 }
8508                 if (wanttangents && !svector3f)
8509                 {
8510                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8511                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8512                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8513                 }
8514         }
8515 }
8516
8517 float RSurf_FogPoint(const float *v)
8518 {
8519         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8520         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8521         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8522         float FogHeightFade = r_refdef.fogheightfade;
8523         float fogfrac;
8524         unsigned int fogmasktableindex;
8525         if (r_refdef.fogplaneviewabove)
8526                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8527         else
8528                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8529         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8530         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8531 }
8532
8533 float RSurf_FogVertex(const float *v)
8534 {
8535         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8536         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8537         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8538         float FogHeightFade = rsurface.fogheightfade;
8539         float fogfrac;
8540         unsigned int fogmasktableindex;
8541         if (r_refdef.fogplaneviewabove)
8542                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8543         else
8544                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8545         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8546         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8547 }
8548
8549 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8550 {
8551         int i;
8552         for (i = 0;i < numelements;i++)
8553                 outelement3i[i] = inelement3i[i] + adjust;
8554 }
8555
8556 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8557 extern cvar_t gl_vbo;
8558 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8559 {
8560         int deformindex;
8561         int firsttriangle;
8562         int numtriangles;
8563         int firstvertex;
8564         int endvertex;
8565         int numvertices;
8566         int surfacefirsttriangle;
8567         int surfacenumtriangles;
8568         int surfacefirstvertex;
8569         int surfaceendvertex;
8570         int surfacenumvertices;
8571         int batchnumvertices;
8572         int batchnumtriangles;
8573         int needsupdate;
8574         int i, j;
8575         qboolean gaps;
8576         qboolean dynamicvertex;
8577         float amplitude;
8578         float animpos;
8579         float scale;
8580         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8581         float waveparms[4];
8582         q3shaderinfo_deform_t *deform;
8583         const msurface_t *surface, *firstsurface;
8584         r_vertexmesh_t *vertexmesh;
8585         if (!texturenumsurfaces)
8586                 return;
8587         // find vertex range of this surface batch
8588         gaps = false;
8589         firstsurface = texturesurfacelist[0];
8590         firsttriangle = firstsurface->num_firsttriangle;
8591         batchnumvertices = 0;
8592         batchnumtriangles = 0;
8593         firstvertex = endvertex = firstsurface->num_firstvertex;
8594         for (i = 0;i < texturenumsurfaces;i++)
8595         {
8596                 surface = texturesurfacelist[i];
8597                 if (surface != firstsurface + i)
8598                         gaps = true;
8599                 surfacefirstvertex = surface->num_firstvertex;
8600                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8601                 surfacenumvertices = surface->num_vertices;
8602                 surfacenumtriangles = surface->num_triangles;
8603                 if (firstvertex > surfacefirstvertex)
8604                         firstvertex = surfacefirstvertex;
8605                 if (endvertex < surfaceendvertex)
8606                         endvertex = surfaceendvertex;
8607                 batchnumvertices += surfacenumvertices;
8608                 batchnumtriangles += surfacenumtriangles;
8609         }
8610
8611         // we now know the vertex range used, and if there are any gaps in it
8612         rsurface.batchfirstvertex = firstvertex;
8613         rsurface.batchnumvertices = endvertex - firstvertex;
8614         rsurface.batchfirsttriangle = firsttriangle;
8615         rsurface.batchnumtriangles = batchnumtriangles;
8616
8617         // this variable holds flags for which properties have been updated that
8618         // may require regenerating vertexmesh array...
8619         needsupdate = 0;
8620
8621         // check if any dynamic vertex processing must occur
8622         dynamicvertex = false;
8623
8624         // if there is a chance of animated vertex colors, it's a dynamic batch
8625         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8626         {
8627                 dynamicvertex = true;
8628                 batchneed |= BATCHNEED_NOGAPS;
8629                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8630         }
8631
8632         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8633         {
8634                 switch (deform->deform)
8635                 {
8636                 default:
8637                 case Q3DEFORM_PROJECTIONSHADOW:
8638                 case Q3DEFORM_TEXT0:
8639                 case Q3DEFORM_TEXT1:
8640                 case Q3DEFORM_TEXT2:
8641                 case Q3DEFORM_TEXT3:
8642                 case Q3DEFORM_TEXT4:
8643                 case Q3DEFORM_TEXT5:
8644                 case Q3DEFORM_TEXT6:
8645                 case Q3DEFORM_TEXT7:
8646                 case Q3DEFORM_NONE:
8647                         break;
8648                 case Q3DEFORM_AUTOSPRITE:
8649                         dynamicvertex = true;
8650                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8651                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8652                         break;
8653                 case Q3DEFORM_AUTOSPRITE2:
8654                         dynamicvertex = true;
8655                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8656                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8657                         break;
8658                 case Q3DEFORM_NORMAL:
8659                         dynamicvertex = true;
8660                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8661                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8662                         break;
8663                 case Q3DEFORM_WAVE:
8664                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8665                                 break; // if wavefunc is a nop, ignore this transform
8666                         dynamicvertex = true;
8667                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8668                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8669                         break;
8670                 case Q3DEFORM_BULGE:
8671                         dynamicvertex = true;
8672                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8673                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8674                         break;
8675                 case Q3DEFORM_MOVE:
8676                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8677                                 break; // if wavefunc is a nop, ignore this transform
8678                         dynamicvertex = true;
8679                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8680                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8681                         break;
8682                 }
8683         }
8684         switch(rsurface.texture->tcgen.tcgen)
8685         {
8686         default:
8687         case Q3TCGEN_TEXTURE:
8688                 break;
8689         case Q3TCGEN_LIGHTMAP:
8690                 dynamicvertex = true;
8691                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8692                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8693                 break;
8694         case Q3TCGEN_VECTOR:
8695                 dynamicvertex = true;
8696                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8697                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8698                 break;
8699         case Q3TCGEN_ENVIRONMENT:
8700                 dynamicvertex = true;
8701                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8702                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8703                 break;
8704         }
8705         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8706         {
8707                 dynamicvertex = true;
8708                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8709                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8710         }
8711
8712         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8713         {
8714                 dynamicvertex = true;
8715                 batchneed |= BATCHNEED_NOGAPS;
8716                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8717         }
8718
8719         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8720         {
8721                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8722                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8723                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8724                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8725                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8726                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8727                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8728         }
8729
8730         // when the model data has no vertex buffer (dynamic mesh), we need to
8731         // eliminate gaps
8732         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8733                 batchneed |= BATCHNEED_NOGAPS;
8734
8735         // if needsupdate, we have to do a dynamic vertex batch for sure
8736         if (needsupdate & batchneed)
8737                 dynamicvertex = true;
8738
8739         // see if we need to build vertexmesh from arrays
8740         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8741                 dynamicvertex = true;
8742
8743         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8744         // also some drivers strongly dislike firstvertex
8745         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8746                 dynamicvertex = true;
8747
8748         rsurface.batchvertex3f = rsurface.modelvertex3f;
8749         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8750         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8751         rsurface.batchsvector3f = rsurface.modelsvector3f;
8752         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8753         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8754         rsurface.batchtvector3f = rsurface.modeltvector3f;
8755         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8756         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8757         rsurface.batchnormal3f = rsurface.modelnormal3f;
8758         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8759         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8760         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8761         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8762         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8763         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8764         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8765         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8766         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8767         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8768         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8769         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8770         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8771         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8772         rsurface.batchelement3i = rsurface.modelelement3i;
8773         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8774         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8775         rsurface.batchelement3s = rsurface.modelelement3s;
8776         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8777         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8778
8779         // if any dynamic vertex processing has to occur in software, we copy the
8780         // entire surface list together before processing to rebase the vertices
8781         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8782         //
8783         // if any gaps exist and we do not have a static vertex buffer, we have to
8784         // copy the surface list together to avoid wasting upload bandwidth on the
8785         // vertices in the gaps.
8786         //
8787         // if gaps exist and we have a static vertex buffer, we can choose whether
8788         // to combine the index buffer ranges into one dynamic index buffer or
8789         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
8790         //
8791         // in many cases the batch is reduced to one draw call.
8792
8793         rsurface.batchmultidraw = false;
8794         rsurface.batchmultidrawnumsurfaces = 0;
8795         rsurface.batchmultidrawsurfacelist = NULL;
8796
8797         if (!dynamicvertex)
8798         {
8799                 // static vertex data, just set pointers...
8800                 rsurface.batchgeneratedvertex = false;
8801                 // if there are gaps, we want to build a combined index buffer,
8802                 // otherwise use the original static buffer with an appropriate offset
8803                 if (gaps)
8804                 {
8805                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
8806                         {
8807                                 rsurface.batchmultidraw = true;
8808                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
8809                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
8810                                 return;
8811                         }
8812                         // build a new triangle elements array for this batch
8813                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8814                         rsurface.batchfirsttriangle = 0;
8815                         numtriangles = 0;
8816                         for (i = 0;i < texturenumsurfaces;i++)
8817                         {
8818                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8819                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8820                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8821                                 numtriangles += surfacenumtriangles;
8822                         }
8823                         rsurface.batchelement3i_indexbuffer = NULL;
8824                         rsurface.batchelement3i_bufferoffset = 0;
8825                         rsurface.batchelement3s = NULL;
8826                         rsurface.batchelement3s_indexbuffer = NULL;
8827                         rsurface.batchelement3s_bufferoffset = 0;
8828                         if (endvertex <= 65536)
8829                         {
8830                                 // make a 16bit (unsigned short) index array if possible
8831                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8832                                 for (i = 0;i < numtriangles*3;i++)
8833                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8834                         }
8835                 }
8836                 return;
8837         }
8838
8839         // something needs software processing, do it for real...
8840         // we only directly handle separate array data in this case and then
8841         // generate interleaved data if needed...
8842         rsurface.batchgeneratedvertex = true;
8843
8844         // now copy the vertex data into a combined array and make an index array
8845         // (this is what Quake3 does all the time)
8846         //if (gaps || rsurface.batchfirstvertex)
8847         {
8848                 rsurface.batchvertex3fbuffer = NULL;
8849                 rsurface.batchvertexmesh = NULL;
8850                 rsurface.batchvertexmeshbuffer = NULL;
8851                 rsurface.batchvertex3f = NULL;
8852                 rsurface.batchvertex3f_vertexbuffer = NULL;
8853                 rsurface.batchvertex3f_bufferoffset = 0;
8854                 rsurface.batchsvector3f = NULL;
8855                 rsurface.batchsvector3f_vertexbuffer = NULL;
8856                 rsurface.batchsvector3f_bufferoffset = 0;
8857                 rsurface.batchtvector3f = NULL;
8858                 rsurface.batchtvector3f_vertexbuffer = NULL;
8859                 rsurface.batchtvector3f_bufferoffset = 0;
8860                 rsurface.batchnormal3f = NULL;
8861                 rsurface.batchnormal3f_vertexbuffer = NULL;
8862                 rsurface.batchnormal3f_bufferoffset = 0;
8863                 rsurface.batchlightmapcolor4f = NULL;
8864                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8865                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8866                 rsurface.batchtexcoordtexture2f = NULL;
8867                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8868                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8869                 rsurface.batchtexcoordlightmap2f = NULL;
8870                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8871                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8872                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8873                 rsurface.batchelement3i_indexbuffer = NULL;
8874                 rsurface.batchelement3i_bufferoffset = 0;
8875                 rsurface.batchelement3s = NULL;
8876                 rsurface.batchelement3s_indexbuffer = NULL;
8877                 rsurface.batchelement3s_bufferoffset = 0;
8878                 // we'll only be setting up certain arrays as needed
8879                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8880                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8881                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8882                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8883                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8884                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8885                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8886                 {
8887                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8888                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8889                 }
8890                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8891                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8892                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8893                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8894                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8895                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8896                 numvertices = 0;
8897                 numtriangles = 0;
8898                 for (i = 0;i < texturenumsurfaces;i++)
8899                 {
8900                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8901                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8902                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8903                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8904                         // copy only the data requested
8905                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8906                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8907                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8908                         {
8909                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8910                                 {
8911                                         if (rsurface.batchvertex3f)
8912                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8913                                         else
8914                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8915                                 }
8916                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8917                                 {
8918                                         if (rsurface.modelnormal3f)
8919                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8920                                         else
8921                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8922                                 }
8923                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8924                                 {
8925                                         if (rsurface.modelsvector3f)
8926                                         {
8927                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8928                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8929                                         }
8930                                         else
8931                                         {
8932                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8933                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8934                                         }
8935                                 }
8936                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8937                                 {
8938                                         if (rsurface.modellightmapcolor4f)
8939                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8940                                         else
8941                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8942                                 }
8943                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8944                                 {
8945                                         if (rsurface.modeltexcoordtexture2f)
8946                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8947                                         else
8948                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8949                                 }
8950                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8951                                 {
8952                                         if (rsurface.modeltexcoordlightmap2f)
8953                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8954                                         else
8955                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8956                                 }
8957                         }
8958                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8959                         numvertices += surfacenumvertices;
8960                         numtriangles += surfacenumtriangles;
8961                 }
8962
8963                 // generate a 16bit index array as well if possible
8964                 // (in general, dynamic batches fit)
8965                 if (numvertices <= 65536)
8966                 {
8967                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8968                         for (i = 0;i < numtriangles*3;i++)
8969                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8970                 }
8971
8972                 // since we've copied everything, the batch now starts at 0
8973                 rsurface.batchfirstvertex = 0;
8974                 rsurface.batchnumvertices = batchnumvertices;
8975                 rsurface.batchfirsttriangle = 0;
8976                 rsurface.batchnumtriangles = batchnumtriangles;
8977         }
8978
8979         // q1bsp surfaces rendered in vertex color mode have to have colors
8980         // calculated based on lightstyles
8981         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8982         {
8983                 // generate color arrays for the surfaces in this list
8984                 int c[4];
8985                 int scale;
8986                 int size3;
8987                 const int *offsets;
8988                 const unsigned char *lm;
8989                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8990                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8991                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8992                 numvertices = 0;
8993                 for (i = 0;i < texturenumsurfaces;i++)
8994                 {
8995                         surface = texturesurfacelist[i];
8996                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8997                         surfacenumvertices = surface->num_vertices;
8998                         if (surface->lightmapinfo->samples)
8999                         {
9000                                 for (j = 0;j < surfacenumvertices;j++)
9001                                 {
9002                                         lm = surface->lightmapinfo->samples + offsets[j];
9003                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9004                                         VectorScale(lm, scale, c);
9005                                         if (surface->lightmapinfo->styles[1] != 255)
9006                                         {
9007                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9008                                                 lm += size3;
9009                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9010                                                 VectorMA(c, scale, lm, c);
9011                                                 if (surface->lightmapinfo->styles[2] != 255)
9012                                                 {
9013                                                         lm += size3;
9014                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9015                                                         VectorMA(c, scale, lm, c);
9016                                                         if (surface->lightmapinfo->styles[3] != 255)
9017                                                         {
9018                                                                 lm += size3;
9019                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9020                                                                 VectorMA(c, scale, lm, c);
9021                                                         }
9022                                                 }
9023                                         }
9024                                         c[0] >>= 7;
9025                                         c[1] >>= 7;
9026                                         c[2] >>= 7;
9027                                         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);
9028                                         numvertices++;
9029                                 }
9030                         }
9031                         else
9032                         {
9033                                 for (j = 0;j < surfacenumvertices;j++)
9034                                 {
9035                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9036                                         numvertices++;
9037                                 }
9038                         }
9039                 }
9040         }
9041
9042         // if vertices are deformed (sprite flares and things in maps, possibly
9043         // water waves, bulges and other deformations), modify the copied vertices
9044         // in place
9045         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9046         {
9047                 switch (deform->deform)
9048                 {
9049                 default:
9050                 case Q3DEFORM_PROJECTIONSHADOW:
9051                 case Q3DEFORM_TEXT0:
9052                 case Q3DEFORM_TEXT1:
9053                 case Q3DEFORM_TEXT2:
9054                 case Q3DEFORM_TEXT3:
9055                 case Q3DEFORM_TEXT4:
9056                 case Q3DEFORM_TEXT5:
9057                 case Q3DEFORM_TEXT6:
9058                 case Q3DEFORM_TEXT7:
9059                 case Q3DEFORM_NONE:
9060                         break;
9061                 case Q3DEFORM_AUTOSPRITE:
9062                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9063                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9064                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9065                         VectorNormalize(newforward);
9066                         VectorNormalize(newright);
9067                         VectorNormalize(newup);
9068 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9069 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9070 //                      rsurface.batchvertex3f_bufferoffset = 0;
9071 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9072 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9073 //                      rsurface.batchsvector3f_bufferoffset = 0;
9074 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9075 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9076 //                      rsurface.batchtvector3f_bufferoffset = 0;
9077 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9078 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9079 //                      rsurface.batchnormal3f_bufferoffset = 0;
9080                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9081                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9082                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9083                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9084                                 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);
9085                         // a single autosprite surface can contain multiple sprites...
9086                         for (j = 0;j < batchnumvertices - 3;j += 4)
9087                         {
9088                                 VectorClear(center);
9089                                 for (i = 0;i < 4;i++)
9090                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9091                                 VectorScale(center, 0.25f, center);
9092                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9093                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9094                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9095                                 for (i = 0;i < 4;i++)
9096                                 {
9097                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9098                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9099                                 }
9100                         }
9101                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9102                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9103                         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);
9104                         break;
9105                 case Q3DEFORM_AUTOSPRITE2:
9106                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9107                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9108                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9109                         VectorNormalize(newforward);
9110                         VectorNormalize(newright);
9111                         VectorNormalize(newup);
9112 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9113 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9114 //                      rsurface.batchvertex3f_bufferoffset = 0;
9115                         {
9116                                 const float *v1, *v2;
9117                                 vec3_t start, end;
9118                                 float f, l;
9119                                 struct
9120                                 {
9121                                         float length2;
9122                                         const float *v1;
9123                                         const float *v2;
9124                                 }
9125                                 shortest[2];
9126                                 memset(shortest, 0, sizeof(shortest));
9127                                 // a single autosprite surface can contain multiple sprites...
9128                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9129                                 {
9130                                         VectorClear(center);
9131                                         for (i = 0;i < 4;i++)
9132                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9133                                         VectorScale(center, 0.25f, center);
9134                                         // find the two shortest edges, then use them to define the
9135                                         // axis vectors for rotating around the central axis
9136                                         for (i = 0;i < 6;i++)
9137                                         {
9138                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9139                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9140                                                 l = VectorDistance2(v1, v2);
9141                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9142                                                 if (v1[2] != v2[2])
9143                                                         l += (1.0f / 1024.0f);
9144                                                 if (shortest[0].length2 > l || i == 0)
9145                                                 {
9146                                                         shortest[1] = shortest[0];
9147                                                         shortest[0].length2 = l;
9148                                                         shortest[0].v1 = v1;
9149                                                         shortest[0].v2 = v2;
9150                                                 }
9151                                                 else if (shortest[1].length2 > l || i == 1)
9152                                                 {
9153                                                         shortest[1].length2 = l;
9154                                                         shortest[1].v1 = v1;
9155                                                         shortest[1].v2 = v2;
9156                                                 }
9157                                         }
9158                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9159                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9160                                         // this calculates the right vector from the shortest edge
9161                                         // and the up vector from the edge midpoints
9162                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9163                                         VectorNormalize(right);
9164                                         VectorSubtract(end, start, up);
9165                                         VectorNormalize(up);
9166                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9167                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9168                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9169                                         VectorNegate(forward, forward);
9170                                         VectorReflect(forward, 0, up, forward);
9171                                         VectorNormalize(forward);
9172                                         CrossProduct(up, forward, newright);
9173                                         VectorNormalize(newright);
9174                                         // rotate the quad around the up axis vector, this is made
9175                                         // especially easy by the fact we know the quad is flat,
9176                                         // so we only have to subtract the center position and
9177                                         // measure distance along the right vector, and then
9178                                         // multiply that by the newright vector and add back the
9179                                         // center position
9180                                         // we also need to subtract the old position to undo the
9181                                         // displacement from the center, which we do with a
9182                                         // DotProduct, the subtraction/addition of center is also
9183                                         // optimized into DotProducts here
9184                                         l = DotProduct(right, center);
9185                                         for (i = 0;i < 4;i++)
9186                                         {
9187                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9188                                                 f = DotProduct(right, v1) - l;
9189                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9190                                         }
9191                                 }
9192                         }
9193                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9194                         {
9195 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9196 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9197 //                              rsurface.batchnormal3f_bufferoffset = 0;
9198                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9199                         }
9200                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9201                         {
9202 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9203 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9204 //                              rsurface.batchsvector3f_bufferoffset = 0;
9205 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9206 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9207 //                              rsurface.batchtvector3f_bufferoffset = 0;
9208                                 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);
9209                         }
9210                         break;
9211                 case Q3DEFORM_NORMAL:
9212                         // deform the normals to make reflections wavey
9213                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9214                         rsurface.batchnormal3f_vertexbuffer = NULL;
9215                         rsurface.batchnormal3f_bufferoffset = 0;
9216                         for (j = 0;j < batchnumvertices;j++)
9217                         {
9218                                 float vertex[3];
9219                                 float *normal = rsurface.batchnormal3f + 3*j;
9220                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9221                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9222                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9223                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9224                                 VectorNormalize(normal);
9225                         }
9226                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9227                         {
9228 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9229 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9230 //                              rsurface.batchsvector3f_bufferoffset = 0;
9231 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9232 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9233 //                              rsurface.batchtvector3f_bufferoffset = 0;
9234                                 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);
9235                         }
9236                         break;
9237                 case Q3DEFORM_WAVE:
9238                         // deform vertex array to make wavey water and flags and such
9239                         waveparms[0] = deform->waveparms[0];
9240                         waveparms[1] = deform->waveparms[1];
9241                         waveparms[2] = deform->waveparms[2];
9242                         waveparms[3] = deform->waveparms[3];
9243                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9244                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9245                         // this is how a divisor of vertex influence on deformation
9246                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9247                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9248 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9249 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9250 //                      rsurface.batchvertex3f_bufferoffset = 0;
9251 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9252 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9253 //                      rsurface.batchnormal3f_bufferoffset = 0;
9254                         for (j = 0;j < batchnumvertices;j++)
9255                         {
9256                                 // if the wavefunc depends on time, evaluate it per-vertex
9257                                 if (waveparms[3])
9258                                 {
9259                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9260                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9261                                 }
9262                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9263                         }
9264                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9265                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9266                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9267                         {
9268 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9269 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9270 //                              rsurface.batchsvector3f_bufferoffset = 0;
9271 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9272 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9273 //                              rsurface.batchtvector3f_bufferoffset = 0;
9274                                 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);
9275                         }
9276                         break;
9277                 case Q3DEFORM_BULGE:
9278                         // deform vertex array to make the surface have moving bulges
9279 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9280 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9281 //                      rsurface.batchvertex3f_bufferoffset = 0;
9282 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9283 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9284 //                      rsurface.batchnormal3f_bufferoffset = 0;
9285                         for (j = 0;j < batchnumvertices;j++)
9286                         {
9287                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9288                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9289                         }
9290                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9291                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9292                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9293                         {
9294 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9295 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9296 //                              rsurface.batchsvector3f_bufferoffset = 0;
9297 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9298 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9299 //                              rsurface.batchtvector3f_bufferoffset = 0;
9300                                 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);
9301                         }
9302                         break;
9303                 case Q3DEFORM_MOVE:
9304                         // deform vertex array
9305                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9306                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9307                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9308                         VectorScale(deform->parms, scale, waveparms);
9309 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9310 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9311 //                      rsurface.batchvertex3f_bufferoffset = 0;
9312                         for (j = 0;j < batchnumvertices;j++)
9313                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9314                         break;
9315                 }
9316         }
9317
9318         // generate texcoords based on the chosen texcoord source
9319         switch(rsurface.texture->tcgen.tcgen)
9320         {
9321         default:
9322         case Q3TCGEN_TEXTURE:
9323                 break;
9324         case Q3TCGEN_LIGHTMAP:
9325 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9326 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9327 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9328                 if (rsurface.batchtexcoordlightmap2f)
9329                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9330                 break;
9331         case Q3TCGEN_VECTOR:
9332 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9333 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9334 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9335                 for (j = 0;j < batchnumvertices;j++)
9336                 {
9337                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9338                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9339                 }
9340                 break;
9341         case Q3TCGEN_ENVIRONMENT:
9342                 // make environment reflections using a spheremap
9343                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9344                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9345                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9346                 for (j = 0;j < batchnumvertices;j++)
9347                 {
9348                         // identical to Q3A's method, but executed in worldspace so
9349                         // carried models can be shiny too
9350
9351                         float viewer[3], d, reflected[3], worldreflected[3];
9352
9353                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9354                         // VectorNormalize(viewer);
9355
9356                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9357
9358                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9359                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9360                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9361                         // note: this is proportinal to viewer, so we can normalize later
9362
9363                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9364                         VectorNormalize(worldreflected);
9365
9366                         // note: this sphere map only uses world x and z!
9367                         // so positive and negative y will LOOK THE SAME.
9368                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9369                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9370                 }
9371                 break;
9372         }
9373         // the only tcmod that needs software vertex processing is turbulent, so
9374         // check for it here and apply the changes if needed
9375         // and we only support that as the first one
9376         // (handling a mixture of turbulent and other tcmods would be problematic
9377         //  without punting it entirely to a software path)
9378         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9379         {
9380                 amplitude = rsurface.texture->tcmods[0].parms[1];
9381                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9382 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9383 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9384 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9385                 for (j = 0;j < batchnumvertices;j++)
9386                 {
9387                         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);
9388                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9389                 }
9390         }
9391
9392         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9393         {
9394                 // convert the modified arrays to vertex structs
9395 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9396 //              rsurface.batchvertexmeshbuffer = NULL;
9397                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9398                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9399                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9400                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9401                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9402                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9403                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9404                 {
9405                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9406                         {
9407                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9408                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9409                         }
9410                 }
9411                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9412                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9413                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9414                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9415                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9416                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9417                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9418                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9419                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9420         }
9421 }
9422
9423 void RSurf_DrawBatch(void)
9424 {
9425         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9426         // through the pipeline, killing it earlier in the pipeline would have
9427         // per-surface overhead rather than per-batch overhead, so it's best to
9428         // reject it here, before it hits glDraw.
9429         if (rsurface.batchnumtriangles == 0)
9430                 return;
9431 #if 0
9432         // batch debugging code
9433         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9434         {
9435                 int i;
9436                 int j;
9437                 int c;
9438                 const int *e;
9439                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9440                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9441                 {
9442                         c = e[i];
9443                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9444                         {
9445                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9446                                 {
9447                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9448                                                 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);
9449                                         break;
9450                                 }
9451                         }
9452                 }
9453         }
9454 #endif
9455         if (rsurface.batchmultidraw)
9456         {
9457                 // issue multiple draws rather than copying index data
9458                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
9459                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
9460                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
9461                 for (i = 0;i < numsurfaces;)
9462                 {
9463                         // combine consecutive surfaces as one draw
9464                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
9465                                 if (surfacelist[j] != surfacelist[k] + 1)
9466                                         break;
9467                         firstvertex = surfacelist[i]->num_firstvertex;
9468                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
9469                         firsttriangle = surfacelist[i]->num_firsttriangle;
9470                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
9471                         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);
9472                         i = j;
9473                 }
9474         }
9475         else
9476         {
9477                 // there is only one consecutive run of index data (may have been combined)
9478                 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);
9479         }
9480 }
9481
9482 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9483 {
9484         // pick the closest matching water plane
9485         int planeindex, vertexindex, bestplaneindex = -1;
9486         float d, bestd;
9487         vec3_t vert;
9488         const float *v;
9489         r_waterstate_waterplane_t *p;
9490         qboolean prepared = false;
9491         bestd = 0;
9492         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9493         {
9494                 if(p->camera_entity != rsurface.texture->camera_entity)
9495                         continue;
9496                 d = 0;
9497                 if(!prepared)
9498                 {
9499                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9500                         prepared = true;
9501                         if(rsurface.batchnumvertices == 0)
9502                                 break;
9503                 }
9504                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9505                 {
9506                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9507                         d += fabs(PlaneDiff(vert, &p->plane));
9508                 }
9509                 if (bestd > d || bestplaneindex < 0)
9510                 {
9511                         bestd = d;
9512                         bestplaneindex = planeindex;
9513                 }
9514         }
9515         return bestplaneindex;
9516         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9517         // this situation though, as it might be better to render single larger
9518         // batches with useless stuff (backface culled for example) than to
9519         // render multiple smaller batches
9520 }
9521
9522 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9523 {
9524         int i;
9525         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9526         rsurface.passcolor4f_vertexbuffer = 0;
9527         rsurface.passcolor4f_bufferoffset = 0;
9528         for (i = 0;i < rsurface.batchnumvertices;i++)
9529                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9530 }
9531
9532 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9533 {
9534         int i;
9535         float f;
9536         const float *v;
9537         const float *c;
9538         float *c2;
9539         if (rsurface.passcolor4f)
9540         {
9541                 // generate color arrays
9542                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9543                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9544                 rsurface.passcolor4f_vertexbuffer = 0;
9545                 rsurface.passcolor4f_bufferoffset = 0;
9546                 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)
9547                 {
9548                         f = RSurf_FogVertex(v);
9549                         c2[0] = c[0] * f;
9550                         c2[1] = c[1] * f;
9551                         c2[2] = c[2] * f;
9552                         c2[3] = c[3];
9553                 }
9554         }
9555         else
9556         {
9557                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9558                 rsurface.passcolor4f_vertexbuffer = 0;
9559                 rsurface.passcolor4f_bufferoffset = 0;
9560                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9561                 {
9562                         f = RSurf_FogVertex(v);
9563                         c2[0] = f;
9564                         c2[1] = f;
9565                         c2[2] = f;
9566                         c2[3] = 1;
9567                 }
9568         }
9569 }
9570
9571 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9572 {
9573         int i;
9574         float f;
9575         const float *v;
9576         const float *c;
9577         float *c2;
9578         if (!rsurface.passcolor4f)
9579                 return;
9580         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9581         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9582         rsurface.passcolor4f_vertexbuffer = 0;
9583         rsurface.passcolor4f_bufferoffset = 0;
9584         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)
9585         {
9586                 f = RSurf_FogVertex(v);
9587                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9588                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9589                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9590                 c2[3] = c[3];
9591         }
9592 }
9593
9594 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9595 {
9596         int i;
9597         const float *c;
9598         float *c2;
9599         if (!rsurface.passcolor4f)
9600                 return;
9601         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9602         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9603         rsurface.passcolor4f_vertexbuffer = 0;
9604         rsurface.passcolor4f_bufferoffset = 0;
9605         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9606         {
9607                 c2[0] = c[0] * r;
9608                 c2[1] = c[1] * g;
9609                 c2[2] = c[2] * b;
9610                 c2[3] = c[3] * a;
9611         }
9612 }
9613
9614 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9615 {
9616         int i;
9617         const float *c;
9618         float *c2;
9619         if (!rsurface.passcolor4f)
9620                 return;
9621         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9622         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9623         rsurface.passcolor4f_vertexbuffer = 0;
9624         rsurface.passcolor4f_bufferoffset = 0;
9625         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9626         {
9627                 c2[0] = c[0] + r_refdef.scene.ambient;
9628                 c2[1] = c[1] + r_refdef.scene.ambient;
9629                 c2[2] = c[2] + r_refdef.scene.ambient;
9630                 c2[3] = c[3];
9631         }
9632 }
9633
9634 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9635 {
9636         // TODO: optimize
9637         rsurface.passcolor4f = NULL;
9638         rsurface.passcolor4f_vertexbuffer = 0;
9639         rsurface.passcolor4f_bufferoffset = 0;
9640         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9641         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9642         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9643         GL_Color(r, g, b, a);
9644         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9645         RSurf_DrawBatch();
9646 }
9647
9648 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9649 {
9650         // TODO: optimize applyfog && applycolor case
9651         // just apply fog if necessary, and tint the fog color array if necessary
9652         rsurface.passcolor4f = NULL;
9653         rsurface.passcolor4f_vertexbuffer = 0;
9654         rsurface.passcolor4f_bufferoffset = 0;
9655         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9656         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9657         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9658         GL_Color(r, g, b, a);
9659         RSurf_DrawBatch();
9660 }
9661
9662 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9663 {
9664         // TODO: optimize
9665         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9666         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9667         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9668         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9669         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9670         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9671         GL_Color(r, g, b, a);
9672         RSurf_DrawBatch();
9673 }
9674
9675 static void RSurf_DrawBatch_GL11_ClampColor(void)
9676 {
9677         int i;
9678         const float *c1;
9679         float *c2;
9680         if (!rsurface.passcolor4f)
9681                 return;
9682         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9683         {
9684                 c2[0] = bound(0.0f, c1[0], 1.0f);
9685                 c2[1] = bound(0.0f, c1[1], 1.0f);
9686                 c2[2] = bound(0.0f, c1[2], 1.0f);
9687                 c2[3] = bound(0.0f, c1[3], 1.0f);
9688         }
9689 }
9690
9691 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9692 {
9693         int i;
9694         float f;
9695         const float *v;
9696         const float *n;
9697         float *c;
9698         //vec3_t eyedir;
9699
9700         // fake shading
9701         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9702         rsurface.passcolor4f_vertexbuffer = 0;
9703         rsurface.passcolor4f_bufferoffset = 0;
9704         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)
9705         {
9706                 f = -DotProduct(r_refdef.view.forward, n);
9707                 f = max(0, f);
9708                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9709                 f *= r_refdef.lightmapintensity;
9710                 Vector4Set(c, f, f, f, 1);
9711         }
9712 }
9713
9714 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9715 {
9716         RSurf_DrawBatch_GL11_ApplyFakeLight();
9717         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9718         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9719         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9720         GL_Color(r, g, b, a);
9721         RSurf_DrawBatch();
9722 }
9723
9724 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9725 {
9726         int i;
9727         float f;
9728         float alpha;
9729         const float *v;
9730         const float *n;
9731         float *c;
9732         vec3_t ambientcolor;
9733         vec3_t diffusecolor;
9734         vec3_t lightdir;
9735         // TODO: optimize
9736         // model lighting
9737         VectorCopy(rsurface.modellight_lightdir, lightdir);
9738         f = 0.5f * r_refdef.lightmapintensity;
9739         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9740         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9741         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9742         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9743         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9744         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9745         alpha = *a;
9746         if (VectorLength2(diffusecolor) > 0)
9747         {
9748                 // q3-style directional shading
9749                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9750                 rsurface.passcolor4f_vertexbuffer = 0;
9751                 rsurface.passcolor4f_bufferoffset = 0;
9752                 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)
9753                 {
9754                         if ((f = DotProduct(n, lightdir)) > 0)
9755                                 VectorMA(ambientcolor, f, diffusecolor, c);
9756                         else
9757                                 VectorCopy(ambientcolor, c);
9758                         c[3] = alpha;
9759                 }
9760                 *r = 1;
9761                 *g = 1;
9762                 *b = 1;
9763                 *a = 1;
9764                 *applycolor = false;
9765         }
9766         else
9767         {
9768                 *r = ambientcolor[0];
9769                 *g = ambientcolor[1];
9770                 *b = ambientcolor[2];
9771                 rsurface.passcolor4f = NULL;
9772                 rsurface.passcolor4f_vertexbuffer = 0;
9773                 rsurface.passcolor4f_bufferoffset = 0;
9774         }
9775 }
9776
9777 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9778 {
9779         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9780         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9781         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9782         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9783         GL_Color(r, g, b, a);
9784         RSurf_DrawBatch();
9785 }
9786
9787 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9788 {
9789         int i;
9790         float f;
9791         const float *v;
9792         float *c;
9793
9794         // fake shading
9795         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9796         rsurface.passcolor4f_vertexbuffer = 0;
9797         rsurface.passcolor4f_bufferoffset = 0;
9798
9799         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9800         {
9801                 f = 1 - RSurf_FogVertex(v);
9802                 c[0] = r;
9803                 c[1] = g;
9804                 c[2] = b;
9805                 c[3] = f * a;
9806         }
9807 }
9808
9809 void RSurf_SetupDepthAndCulling(void)
9810 {
9811         // submodels are biased to avoid z-fighting with world surfaces that they
9812         // may be exactly overlapping (avoids z-fighting artifacts on certain
9813         // doors and things in Quake maps)
9814         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9815         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9816         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9817         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9818 }
9819
9820 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9821 {
9822         // transparent sky would be ridiculous
9823         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9824                 return;
9825         R_SetupShader_Generic_NoTexture(false, false);
9826         skyrenderlater = true;
9827         RSurf_SetupDepthAndCulling();
9828         GL_DepthMask(true);
9829         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9830         // skymasking on them, and Quake3 never did sky masking (unlike
9831         // software Quake and software Quake2), so disable the sky masking
9832         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9833         // and skymasking also looks very bad when noclipping outside the
9834         // level, so don't use it then either.
9835         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9836         {
9837                 R_Mesh_ResetTextureState();
9838                 if (skyrendermasked)
9839                 {
9840                         R_SetupShader_DepthOrShadow(false, false);
9841                         // depth-only (masking)
9842                         GL_ColorMask(0,0,0,0);
9843                         // just to make sure that braindead drivers don't draw
9844                         // anything despite that colormask...
9845                         GL_BlendFunc(GL_ZERO, GL_ONE);
9846                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9847                         if (rsurface.batchvertex3fbuffer)
9848                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9849                         else
9850                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9851                 }
9852                 else
9853                 {
9854                         R_SetupShader_Generic_NoTexture(false, false);
9855                         // fog sky
9856                         GL_BlendFunc(GL_ONE, GL_ZERO);
9857                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9858                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9859                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9860                 }
9861                 RSurf_DrawBatch();
9862                 if (skyrendermasked)
9863                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9864         }
9865         R_Mesh_ResetTextureState();
9866         GL_Color(1, 1, 1, 1);
9867 }
9868
9869 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9870 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9871 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9872 {
9873         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9874                 return;
9875         if (prepass)
9876         {
9877                 // render screenspace normalmap to texture
9878                 GL_DepthMask(true);
9879                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9880                 RSurf_DrawBatch();
9881                 return;
9882         }
9883
9884         // bind lightmap texture
9885
9886         // water/refraction/reflection/camera surfaces have to be handled specially
9887         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9888         {
9889                 int start, end, startplaneindex;
9890                 for (start = 0;start < texturenumsurfaces;start = end)
9891                 {
9892                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9893                         if(startplaneindex < 0)
9894                         {
9895                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9896                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9897                                 end = start + 1;
9898                                 continue;
9899                         }
9900                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9901                                 ;
9902                         // now that we have a batch using the same planeindex, render it
9903                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9904                         {
9905                                 // render water or distortion background
9906                                 GL_DepthMask(true);
9907                                 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);
9908                                 RSurf_DrawBatch();
9909                                 // blend surface on top
9910                                 GL_DepthMask(false);
9911                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9912                                 RSurf_DrawBatch();
9913                         }
9914                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9915                         {
9916                                 // render surface with reflection texture as input
9917                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9918                                 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);
9919                                 RSurf_DrawBatch();
9920                         }
9921                 }
9922                 return;
9923         }
9924
9925         // render surface batch normally
9926         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9927         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);
9928         RSurf_DrawBatch();
9929 }
9930
9931 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9932 {
9933         // OpenGL 1.3 path - anything not completely ancient
9934         qboolean applycolor;
9935         qboolean applyfog;
9936         int layerindex;
9937         const texturelayer_t *layer;
9938         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);
9939         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9940
9941         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9942         {
9943                 vec4_t layercolor;
9944                 int layertexrgbscale;
9945                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9946                 {
9947                         if (layerindex == 0)
9948                                 GL_AlphaTest(true);
9949                         else
9950                         {
9951                                 GL_AlphaTest(false);
9952                                 GL_DepthFunc(GL_EQUAL);
9953                         }
9954                 }
9955                 GL_DepthMask(layer->depthmask && writedepth);
9956                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9957                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9958                 {
9959                         layertexrgbscale = 4;
9960                         VectorScale(layer->color, 0.25f, layercolor);
9961                 }
9962                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9963                 {
9964                         layertexrgbscale = 2;
9965                         VectorScale(layer->color, 0.5f, layercolor);
9966                 }
9967                 else
9968                 {
9969                         layertexrgbscale = 1;
9970                         VectorScale(layer->color, 1.0f, layercolor);
9971                 }
9972                 layercolor[3] = layer->color[3];
9973                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9974                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9975                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9976                 switch (layer->type)
9977                 {
9978                 case TEXTURELAYERTYPE_LITTEXTURE:
9979                         // single-pass lightmapped texture with 2x rgbscale
9980                         R_Mesh_TexBind(0, r_texture_white);
9981                         R_Mesh_TexMatrix(0, NULL);
9982                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9983                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9984                         R_Mesh_TexBind(1, layer->texture);
9985                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9986                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9987                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9988                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9989                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9990                         else if (FAKELIGHT_ENABLED)
9991                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9992                         else if (rsurface.uselightmaptexture)
9993                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9994                         else
9995                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9996                         break;
9997                 case TEXTURELAYERTYPE_TEXTURE:
9998                         // singletexture unlit texture with transparency support
9999                         R_Mesh_TexBind(0, layer->texture);
10000                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10001                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10002                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10003                         R_Mesh_TexBind(1, 0);
10004                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10005                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10006                         break;
10007                 case TEXTURELAYERTYPE_FOG:
10008                         // singletexture fogging
10009                         if (layer->texture)
10010                         {
10011                                 R_Mesh_TexBind(0, layer->texture);
10012                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10013                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10014                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10015                         }
10016                         else
10017                         {
10018                                 R_Mesh_TexBind(0, 0);
10019                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10020                         }
10021                         R_Mesh_TexBind(1, 0);
10022                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10023                         // generate a color array for the fog pass
10024                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10025                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10026                         RSurf_DrawBatch();
10027                         break;
10028                 default:
10029                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10030                 }
10031         }
10032         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10033         {
10034                 GL_DepthFunc(GL_LEQUAL);
10035                 GL_AlphaTest(false);
10036         }
10037 }
10038
10039 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10040 {
10041         // OpenGL 1.1 - crusty old voodoo path
10042         qboolean applyfog;
10043         int layerindex;
10044         const texturelayer_t *layer;
10045         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);
10046         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10047
10048         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10049         {
10050                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10051                 {
10052                         if (layerindex == 0)
10053                                 GL_AlphaTest(true);
10054                         else
10055                         {
10056                                 GL_AlphaTest(false);
10057                                 GL_DepthFunc(GL_EQUAL);
10058                         }
10059                 }
10060                 GL_DepthMask(layer->depthmask && writedepth);
10061                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10062                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10063                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10064                 switch (layer->type)
10065                 {
10066                 case TEXTURELAYERTYPE_LITTEXTURE:
10067                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10068                         {
10069                                 // two-pass lit texture with 2x rgbscale
10070                                 // first the lightmap pass
10071                                 R_Mesh_TexBind(0, r_texture_white);
10072                                 R_Mesh_TexMatrix(0, NULL);
10073                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10074                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10075                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10076                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10077                                 else if (FAKELIGHT_ENABLED)
10078                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10079                                 else if (rsurface.uselightmaptexture)
10080                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10081                                 else
10082                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10083                                 // then apply the texture to it
10084                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10085                                 R_Mesh_TexBind(0, layer->texture);
10086                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10087                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10088                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10089                                 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);
10090                         }
10091                         else
10092                         {
10093                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10094                                 R_Mesh_TexBind(0, layer->texture);
10095                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10096                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10097                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10098                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10099                                         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);
10100                                 else if (FAKELIGHT_ENABLED)
10101                                         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);
10102                                 else
10103                                         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);
10104                         }
10105                         break;
10106                 case TEXTURELAYERTYPE_TEXTURE:
10107                         // singletexture unlit texture with transparency support
10108                         R_Mesh_TexBind(0, layer->texture);
10109                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10110                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10111                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10112                         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);
10113                         break;
10114                 case TEXTURELAYERTYPE_FOG:
10115                         // singletexture fogging
10116                         if (layer->texture)
10117                         {
10118                                 R_Mesh_TexBind(0, layer->texture);
10119                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10120                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10121                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10122                         }
10123                         else
10124                         {
10125                                 R_Mesh_TexBind(0, 0);
10126                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10127                         }
10128                         // generate a color array for the fog pass
10129                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10130                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10131                         RSurf_DrawBatch();
10132                         break;
10133                 default:
10134                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10135                 }
10136         }
10137         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10138         {
10139                 GL_DepthFunc(GL_LEQUAL);
10140                 GL_AlphaTest(false);
10141         }
10142 }
10143
10144 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10145 {
10146         int vi;
10147         int j;
10148         r_vertexgeneric_t *batchvertex;
10149         float c[4];
10150
10151 //      R_Mesh_ResetTextureState();
10152         R_SetupShader_Generic_NoTexture(false, false);
10153
10154         if(rsurface.texture && rsurface.texture->currentskinframe)
10155         {
10156                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10157                 c[3] *= rsurface.texture->currentalpha;
10158         }
10159         else
10160         {
10161                 c[0] = 1;
10162                 c[1] = 0;
10163                 c[2] = 1;
10164                 c[3] = 1;
10165         }
10166
10167         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10168         {
10169                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10170                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10171                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10172         }
10173
10174         // brighten it up (as texture value 127 means "unlit")
10175         c[0] *= 2 * r_refdef.view.colorscale;
10176         c[1] *= 2 * r_refdef.view.colorscale;
10177         c[2] *= 2 * r_refdef.view.colorscale;
10178
10179         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10180                 c[3] *= r_wateralpha.value;
10181
10182         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10183         {
10184                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10185                 GL_DepthMask(false);
10186         }
10187         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10188         {
10189                 GL_BlendFunc(GL_ONE, GL_ONE);
10190                 GL_DepthMask(false);
10191         }
10192         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10193         {
10194                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10195                 GL_DepthMask(false);
10196         }
10197         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10198         {
10199                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10200                 GL_DepthMask(false);
10201         }
10202         else
10203         {
10204                 GL_BlendFunc(GL_ONE, GL_ZERO);
10205                 GL_DepthMask(writedepth);
10206         }
10207
10208         if (r_showsurfaces.integer == 3)
10209         {
10210                 rsurface.passcolor4f = NULL;
10211
10212                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10213                 {
10214                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10215
10216                         rsurface.passcolor4f = NULL;
10217                         rsurface.passcolor4f_vertexbuffer = 0;
10218                         rsurface.passcolor4f_bufferoffset = 0;
10219                 }
10220                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10221                 {
10222                         qboolean applycolor = true;
10223                         float one = 1.0;
10224
10225                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10226
10227                         r_refdef.lightmapintensity = 1;
10228                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10229                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10230                 }
10231                 else if (FAKELIGHT_ENABLED)
10232                 {
10233                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10234
10235                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10236                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10237                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10238                 }
10239                 else
10240                 {
10241                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10242
10243                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10244                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10245                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10246                 }
10247
10248                 if(!rsurface.passcolor4f)
10249                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10250
10251                 RSurf_DrawBatch_GL11_ApplyAmbient();
10252                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10253                 if(r_refdef.fogenabled)
10254                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10255                 RSurf_DrawBatch_GL11_ClampColor();
10256
10257                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10258                 R_SetupShader_Generic_NoTexture(false, false);
10259                 RSurf_DrawBatch();
10260         }
10261         else if (!r_refdef.view.showdebug)
10262         {
10263                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10264                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10265                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10266                 {
10267                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10268                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10269                 }
10270                 R_Mesh_PrepareVertices_Generic_Unlock();
10271                 RSurf_DrawBatch();
10272         }
10273         else if (r_showsurfaces.integer == 4)
10274         {
10275                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10276                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10277                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10278                 {
10279                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10280                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10281                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10282                 }
10283                 R_Mesh_PrepareVertices_Generic_Unlock();
10284                 RSurf_DrawBatch();
10285         }
10286         else if (r_showsurfaces.integer == 2)
10287         {
10288                 const int *e;
10289                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10290                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10291                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10292                 {
10293                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10294                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10295                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10296                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10297                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10298                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10299                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10300                 }
10301                 R_Mesh_PrepareVertices_Generic_Unlock();
10302                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10303         }
10304         else
10305         {
10306                 int texturesurfaceindex;
10307                 int k;
10308                 const msurface_t *surface;
10309                 float surfacecolor4f[4];
10310                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10311                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10312                 vi = 0;
10313                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10314                 {
10315                         surface = texturesurfacelist[texturesurfaceindex];
10316                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10317                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10318                         for (j = 0;j < surface->num_vertices;j++)
10319                         {
10320                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10321                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10322                                 vi++;
10323                         }
10324                 }
10325                 R_Mesh_PrepareVertices_Generic_Unlock();
10326                 RSurf_DrawBatch();
10327         }
10328 }
10329
10330 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10331 {
10332         CHECKGLERROR
10333         RSurf_SetupDepthAndCulling();
10334         if (r_showsurfaces.integer)
10335         {
10336                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10337                 return;
10338         }
10339         switch (vid.renderpath)
10340         {
10341         case RENDERPATH_GL20:
10342         case RENDERPATH_D3D9:
10343         case RENDERPATH_D3D10:
10344         case RENDERPATH_D3D11:
10345         case RENDERPATH_SOFT:
10346         case RENDERPATH_GLES2:
10347                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10348                 break;
10349         case RENDERPATH_GL13:
10350         case RENDERPATH_GLES1:
10351                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10352                 break;
10353         case RENDERPATH_GL11:
10354                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10355                 break;
10356         }
10357         CHECKGLERROR
10358 }
10359
10360 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10361 {
10362         CHECKGLERROR
10363         RSurf_SetupDepthAndCulling();
10364         if (r_showsurfaces.integer)
10365         {
10366                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10367                 return;
10368         }
10369         switch (vid.renderpath)
10370         {
10371         case RENDERPATH_GL20:
10372         case RENDERPATH_D3D9:
10373         case RENDERPATH_D3D10:
10374         case RENDERPATH_D3D11:
10375         case RENDERPATH_SOFT:
10376         case RENDERPATH_GLES2:
10377                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10378                 break;
10379         case RENDERPATH_GL13:
10380         case RENDERPATH_GLES1:
10381                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10382                 break;
10383         case RENDERPATH_GL11:
10384                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10385                 break;
10386         }
10387         CHECKGLERROR
10388 }
10389
10390 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10391 {
10392         int i, j;
10393         int texturenumsurfaces, endsurface;
10394         texture_t *texture;
10395         const msurface_t *surface;
10396         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10397
10398         // if the model is static it doesn't matter what value we give for
10399         // wantnormals and wanttangents, so this logic uses only rules applicable
10400         // to a model, knowing that they are meaningless otherwise
10401         if (ent == r_refdef.scene.worldentity)
10402                 RSurf_ActiveWorldEntity();
10403         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10404                 RSurf_ActiveModelEntity(ent, false, false, false);
10405         else
10406         {
10407                 switch (vid.renderpath)
10408                 {
10409                 case RENDERPATH_GL20:
10410                 case RENDERPATH_D3D9:
10411                 case RENDERPATH_D3D10:
10412                 case RENDERPATH_D3D11:
10413                 case RENDERPATH_SOFT:
10414                 case RENDERPATH_GLES2:
10415                         RSurf_ActiveModelEntity(ent, true, true, false);
10416                         break;
10417                 case RENDERPATH_GL11:
10418                 case RENDERPATH_GL13:
10419                 case RENDERPATH_GLES1:
10420                         RSurf_ActiveModelEntity(ent, true, false, false);
10421                         break;
10422                 }
10423         }
10424
10425         if (r_transparentdepthmasking.integer)
10426         {
10427                 qboolean setup = false;
10428                 for (i = 0;i < numsurfaces;i = j)
10429                 {
10430                         j = i + 1;
10431                         surface = rsurface.modelsurfaces + surfacelist[i];
10432                         texture = surface->texture;
10433                         rsurface.texture = R_GetCurrentTexture(texture);
10434                         rsurface.lightmaptexture = NULL;
10435                         rsurface.deluxemaptexture = NULL;
10436                         rsurface.uselightmaptexture = false;
10437                         // scan ahead until we find a different texture
10438                         endsurface = min(i + 1024, numsurfaces);
10439                         texturenumsurfaces = 0;
10440                         texturesurfacelist[texturenumsurfaces++] = surface;
10441                         for (;j < endsurface;j++)
10442                         {
10443                                 surface = rsurface.modelsurfaces + surfacelist[j];
10444                                 if (texture != surface->texture)
10445                                         break;
10446                                 texturesurfacelist[texturenumsurfaces++] = surface;
10447                         }
10448                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10449                                 continue;
10450                         // render the range of surfaces as depth
10451                         if (!setup)
10452                         {
10453                                 setup = true;
10454                                 GL_ColorMask(0,0,0,0);
10455                                 GL_Color(1,1,1,1);
10456                                 GL_DepthTest(true);
10457                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10458                                 GL_DepthMask(true);
10459 //                              R_Mesh_ResetTextureState();
10460                                 R_SetupShader_DepthOrShadow(false, false);
10461                         }
10462                         RSurf_SetupDepthAndCulling();
10463                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10464                         if (rsurface.batchvertex3fbuffer)
10465                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10466                         else
10467                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10468                         RSurf_DrawBatch();
10469                 }
10470                 if (setup)
10471                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10472         }
10473
10474         for (i = 0;i < numsurfaces;i = j)
10475         {
10476                 j = i + 1;
10477                 surface = rsurface.modelsurfaces + surfacelist[i];
10478                 texture = surface->texture;
10479                 rsurface.texture = R_GetCurrentTexture(texture);
10480                 // scan ahead until we find a different texture
10481                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10482                 texturenumsurfaces = 0;
10483                 texturesurfacelist[texturenumsurfaces++] = surface;
10484                 if(FAKELIGHT_ENABLED)
10485                 {
10486                         rsurface.lightmaptexture = NULL;
10487                         rsurface.deluxemaptexture = NULL;
10488                         rsurface.uselightmaptexture = false;
10489                         for (;j < endsurface;j++)
10490                         {
10491                                 surface = rsurface.modelsurfaces + surfacelist[j];
10492                                 if (texture != surface->texture)
10493                                         break;
10494                                 texturesurfacelist[texturenumsurfaces++] = surface;
10495                         }
10496                 }
10497                 else
10498                 {
10499                         rsurface.lightmaptexture = surface->lightmaptexture;
10500                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10501                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10502                         for (;j < endsurface;j++)
10503                         {
10504                                 surface = rsurface.modelsurfaces + surfacelist[j];
10505                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10506                                         break;
10507                                 texturesurfacelist[texturenumsurfaces++] = surface;
10508                         }
10509                 }
10510                 // render the range of surfaces
10511                 if (ent == r_refdef.scene.worldentity)
10512                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10513                 else
10514                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10515         }
10516         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10517 }
10518
10519 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10520 {
10521         // transparent surfaces get pushed off into the transparent queue
10522         int surfacelistindex;
10523         const msurface_t *surface;
10524         vec3_t tempcenter, center;
10525         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10526         {
10527                 surface = texturesurfacelist[surfacelistindex];
10528                 if (r_transparent_sortsurfacesbynearest.integer)
10529                 {
10530                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10531                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10532                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10533                 }
10534                 else
10535                 {
10536                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10537                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10538                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10539                 }
10540                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10541                 if (rsurface.entity->transparent_offset) // transparent offset
10542                 {
10543                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10544                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10545                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10546                 }
10547                 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);
10548         }
10549 }
10550
10551 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10552 {
10553         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10554                 return;
10555         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10556                 return;
10557         RSurf_SetupDepthAndCulling();
10558         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10559         if (rsurface.batchvertex3fbuffer)
10560                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10561         else
10562                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10563         RSurf_DrawBatch();
10564 }
10565
10566 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10567 {
10568         CHECKGLERROR
10569         if (depthonly)
10570                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10571         else if (prepass)
10572         {
10573                 if (!rsurface.texture->currentnumlayers)
10574                         return;
10575                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10576                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10577                 else
10578                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10579         }
10580         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10581                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10582         else if (!rsurface.texture->currentnumlayers)
10583                 return;
10584         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10585         {
10586                 // in the deferred case, transparent surfaces were queued during prepass
10587                 if (!r_shadow_usingdeferredprepass)
10588                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10589         }
10590         else
10591         {
10592                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10593                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10594         }
10595         CHECKGLERROR
10596 }
10597
10598 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10599 {
10600         int i, j;
10601         texture_t *texture;
10602         R_FrameData_SetMark();
10603         // break the surface list down into batches by texture and use of lightmapping
10604         for (i = 0;i < numsurfaces;i = j)
10605         {
10606                 j = i + 1;
10607                 // texture is the base texture pointer, rsurface.texture is the
10608                 // current frame/skin the texture is directing us to use (for example
10609                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10610                 // use skin 1 instead)
10611                 texture = surfacelist[i]->texture;
10612                 rsurface.texture = R_GetCurrentTexture(texture);
10613                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10614                 {
10615                         // if this texture is not the kind we want, skip ahead to the next one
10616                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10617                                 ;
10618                         continue;
10619                 }
10620                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10621                 {
10622                         rsurface.lightmaptexture = NULL;
10623                         rsurface.deluxemaptexture = NULL;
10624                         rsurface.uselightmaptexture = false;
10625                         // simply scan ahead until we find a different texture or lightmap state
10626                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10627                                 ;
10628                 }
10629                 else
10630                 {
10631                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10632                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10633                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10634                         // simply scan ahead until we find a different texture or lightmap state
10635                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10636                                 ;
10637                 }
10638                 // render the range of surfaces
10639                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10640         }
10641         R_FrameData_ReturnToMark();
10642 }
10643
10644 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10645 {
10646         CHECKGLERROR
10647         if (depthonly)
10648                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10649         else if (prepass)
10650         {
10651                 if (!rsurface.texture->currentnumlayers)
10652                         return;
10653                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10654                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10655                 else
10656                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10657         }
10658         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10659                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10660         else if (!rsurface.texture->currentnumlayers)
10661                 return;
10662         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10663         {
10664                 // in the deferred case, transparent surfaces were queued during prepass
10665                 if (!r_shadow_usingdeferredprepass)
10666                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10667         }
10668         else
10669         {
10670                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10671                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10672         }
10673         CHECKGLERROR
10674 }
10675
10676 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10677 {
10678         int i, j;
10679         texture_t *texture;
10680         R_FrameData_SetMark();
10681         // break the surface list down into batches by texture and use of lightmapping
10682         for (i = 0;i < numsurfaces;i = j)
10683         {
10684                 j = i + 1;
10685                 // texture is the base texture pointer, rsurface.texture is the
10686                 // current frame/skin the texture is directing us to use (for example
10687                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10688                 // use skin 1 instead)
10689                 texture = surfacelist[i]->texture;
10690                 rsurface.texture = R_GetCurrentTexture(texture);
10691                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10692                 {
10693                         // if this texture is not the kind we want, skip ahead to the next one
10694                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10695                                 ;
10696                         continue;
10697                 }
10698                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10699                 {
10700                         rsurface.lightmaptexture = NULL;
10701                         rsurface.deluxemaptexture = NULL;
10702                         rsurface.uselightmaptexture = false;
10703                         // simply scan ahead until we find a different texture or lightmap state
10704                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10705                                 ;
10706                 }
10707                 else
10708                 {
10709                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10710                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10711                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10712                         // simply scan ahead until we find a different texture or lightmap state
10713                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10714                                 ;
10715                 }
10716                 // render the range of surfaces
10717                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10718         }
10719         R_FrameData_ReturnToMark();
10720 }
10721
10722 float locboxvertex3f[6*4*3] =
10723 {
10724         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10725         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10726         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10727         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10728         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10729         1,0,0, 0,0,0, 0,1,0, 1,1,0
10730 };
10731
10732 unsigned short locboxelements[6*2*3] =
10733 {
10734          0, 1, 2, 0, 2, 3,
10735          4, 5, 6, 4, 6, 7,
10736          8, 9,10, 8,10,11,
10737         12,13,14, 12,14,15,
10738         16,17,18, 16,18,19,
10739         20,21,22, 20,22,23
10740 };
10741
10742 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10743 {
10744         int i, j;
10745         cl_locnode_t *loc = (cl_locnode_t *)ent;
10746         vec3_t mins, size;
10747         float vertex3f[6*4*3];
10748         CHECKGLERROR
10749         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10750         GL_DepthMask(false);
10751         GL_DepthRange(0, 1);
10752         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10753         GL_DepthTest(true);
10754         GL_CullFace(GL_NONE);
10755         R_EntityMatrix(&identitymatrix);
10756
10757 //      R_Mesh_ResetTextureState();
10758
10759         i = surfacelist[0];
10760         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10761                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10762                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10763                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10764
10765         if (VectorCompare(loc->mins, loc->maxs))
10766         {
10767                 VectorSet(size, 2, 2, 2);
10768                 VectorMA(loc->mins, -0.5f, size, mins);
10769         }
10770         else
10771         {
10772                 VectorCopy(loc->mins, mins);
10773                 VectorSubtract(loc->maxs, loc->mins, size);
10774         }
10775
10776         for (i = 0;i < 6*4*3;)
10777                 for (j = 0;j < 3;j++, i++)
10778                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10779
10780         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10781         R_SetupShader_Generic_NoTexture(false, false);
10782         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10783 }
10784
10785 void R_DrawLocs(void)
10786 {
10787         int index;
10788         cl_locnode_t *loc, *nearestloc;
10789         vec3_t center;
10790         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10791         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10792         {
10793                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10794                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10795         }
10796 }
10797
10798 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10799 {
10800         if (decalsystem->decals)
10801                 Mem_Free(decalsystem->decals);
10802         memset(decalsystem, 0, sizeof(*decalsystem));
10803 }
10804
10805 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)
10806 {
10807         tridecal_t *decal;
10808         tridecal_t *decals;
10809         int i;
10810
10811         // expand or initialize the system
10812         if (decalsystem->maxdecals <= decalsystem->numdecals)
10813         {
10814                 decalsystem_t old = *decalsystem;
10815                 qboolean useshortelements;
10816                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10817                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10818                 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)));
10819                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10820                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10821                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10822                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10823                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10824                 if (decalsystem->numdecals)
10825                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10826                 if (old.decals)
10827                         Mem_Free(old.decals);
10828                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10829                         decalsystem->element3i[i] = i;
10830                 if (useshortelements)
10831                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10832                                 decalsystem->element3s[i] = i;
10833         }
10834
10835         // grab a decal and search for another free slot for the next one
10836         decals = decalsystem->decals;
10837         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10838         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10839                 ;
10840         decalsystem->freedecal = i;
10841         if (decalsystem->numdecals <= i)
10842                 decalsystem->numdecals = i + 1;
10843
10844         // initialize the decal
10845         decal->lived = 0;
10846         decal->triangleindex = triangleindex;
10847         decal->surfaceindex = surfaceindex;
10848         decal->decalsequence = decalsequence;
10849         decal->color4f[0][0] = c0[0];
10850         decal->color4f[0][1] = c0[1];
10851         decal->color4f[0][2] = c0[2];
10852         decal->color4f[0][3] = 1;
10853         decal->color4f[1][0] = c1[0];
10854         decal->color4f[1][1] = c1[1];
10855         decal->color4f[1][2] = c1[2];
10856         decal->color4f[1][3] = 1;
10857         decal->color4f[2][0] = c2[0];
10858         decal->color4f[2][1] = c2[1];
10859         decal->color4f[2][2] = c2[2];
10860         decal->color4f[2][3] = 1;
10861         decal->vertex3f[0][0] = v0[0];
10862         decal->vertex3f[0][1] = v0[1];
10863         decal->vertex3f[0][2] = v0[2];
10864         decal->vertex3f[1][0] = v1[0];
10865         decal->vertex3f[1][1] = v1[1];
10866         decal->vertex3f[1][2] = v1[2];
10867         decal->vertex3f[2][0] = v2[0];
10868         decal->vertex3f[2][1] = v2[1];
10869         decal->vertex3f[2][2] = v2[2];
10870         decal->texcoord2f[0][0] = t0[0];
10871         decal->texcoord2f[0][1] = t0[1];
10872         decal->texcoord2f[1][0] = t1[0];
10873         decal->texcoord2f[1][1] = t1[1];
10874         decal->texcoord2f[2][0] = t2[0];
10875         decal->texcoord2f[2][1] = t2[1];
10876         TriangleNormal(v0, v1, v2, decal->plane);
10877         VectorNormalize(decal->plane);
10878         decal->plane[3] = DotProduct(v0, decal->plane);
10879 }
10880
10881 extern cvar_t cl_decals_bias;
10882 extern cvar_t cl_decals_models;
10883 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10884 // baseparms, parms, temps
10885 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)
10886 {
10887         int cornerindex;
10888         int index;
10889         float v[9][3];
10890         const float *vertex3f;
10891         const float *normal3f;
10892         int numpoints;
10893         float points[2][9][3];
10894         float temp[3];
10895         float tc[9][2];
10896         float f;
10897         float c[9][4];
10898         const int *e;
10899
10900         e = rsurface.modelelement3i + 3*triangleindex;
10901
10902         vertex3f = rsurface.modelvertex3f;
10903         normal3f = rsurface.modelnormal3f;
10904
10905         if (normal3f)
10906         {
10907                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10908                 {
10909                         index = 3*e[cornerindex];
10910                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10911                 }
10912         }
10913         else
10914         {
10915                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10916                 {
10917                         index = 3*e[cornerindex];
10918                         VectorCopy(vertex3f + index, v[cornerindex]);
10919                 }
10920         }
10921
10922         // cull backfaces
10923         //TriangleNormal(v[0], v[1], v[2], normal);
10924         //if (DotProduct(normal, localnormal) < 0.0f)
10925         //      continue;
10926         // clip by each of the box planes formed from the projection matrix
10927         // if anything survives, we emit the decal
10928         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]);
10929         if (numpoints < 3)
10930                 return;
10931         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]);
10932         if (numpoints < 3)
10933                 return;
10934         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]);
10935         if (numpoints < 3)
10936                 return;
10937         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]);
10938         if (numpoints < 3)
10939                 return;
10940         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]);
10941         if (numpoints < 3)
10942                 return;
10943         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]);
10944         if (numpoints < 3)
10945                 return;
10946         // some part of the triangle survived, so we have to accept it...
10947         if (dynamic)
10948         {
10949                 // dynamic always uses the original triangle
10950                 numpoints = 3;
10951                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10952                 {
10953                         index = 3*e[cornerindex];
10954                         VectorCopy(vertex3f + index, v[cornerindex]);
10955                 }
10956         }
10957         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10958         {
10959                 // convert vertex positions to texcoords
10960                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10961                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10962                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10963                 // calculate distance fade from the projection origin
10964                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10965                 f = bound(0.0f, f, 1.0f);
10966                 c[cornerindex][0] = r * f;
10967                 c[cornerindex][1] = g * f;
10968                 c[cornerindex][2] = b * f;
10969                 c[cornerindex][3] = 1.0f;
10970                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10971         }
10972         if (dynamic)
10973                 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);
10974         else
10975                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10976                         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);
10977 }
10978 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)
10979 {
10980         matrix4x4_t projection;
10981         decalsystem_t *decalsystem;
10982         qboolean dynamic;
10983         dp_model_t *model;
10984         const msurface_t *surface;
10985         const msurface_t *surfaces;
10986         const int *surfacelist;
10987         const texture_t *texture;
10988         int numtriangles;
10989         int numsurfacelist;
10990         int surfacelistindex;
10991         int surfaceindex;
10992         int triangleindex;
10993         float localorigin[3];
10994         float localnormal[3];
10995         float localmins[3];
10996         float localmaxs[3];
10997         float localsize;
10998         //float normal[3];
10999         float planes[6][4];
11000         float angles[3];
11001         bih_t *bih;
11002         int bih_triangles_count;
11003         int bih_triangles[256];
11004         int bih_surfaces[256];
11005
11006         decalsystem = &ent->decalsystem;
11007         model = ent->model;
11008         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11009         {
11010                 R_DecalSystem_Reset(&ent->decalsystem);
11011                 return;
11012         }
11013
11014         if (!model->brush.data_leafs && !cl_decals_models.integer)
11015         {
11016                 if (decalsystem->model)
11017                         R_DecalSystem_Reset(decalsystem);
11018                 return;
11019         }
11020
11021         if (decalsystem->model != model)
11022                 R_DecalSystem_Reset(decalsystem);
11023         decalsystem->model = model;
11024
11025         RSurf_ActiveModelEntity(ent, true, false, false);
11026
11027         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11028         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11029         VectorNormalize(localnormal);
11030         localsize = worldsize*rsurface.inversematrixscale;
11031         localmins[0] = localorigin[0] - localsize;
11032         localmins[1] = localorigin[1] - localsize;
11033         localmins[2] = localorigin[2] - localsize;
11034         localmaxs[0] = localorigin[0] + localsize;
11035         localmaxs[1] = localorigin[1] + localsize;
11036         localmaxs[2] = localorigin[2] + localsize;
11037
11038         //VectorCopy(localnormal, planes[4]);
11039         //VectorVectors(planes[4], planes[2], planes[0]);
11040         AnglesFromVectors(angles, localnormal, NULL, false);
11041         AngleVectors(angles, planes[0], planes[2], planes[4]);
11042         VectorNegate(planes[0], planes[1]);
11043         VectorNegate(planes[2], planes[3]);
11044         VectorNegate(planes[4], planes[5]);
11045         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11046         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11047         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11048         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11049         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11050         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11051
11052 #if 1
11053 // works
11054 {
11055         matrix4x4_t forwardprojection;
11056         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11057         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11058 }
11059 #else
11060 // broken
11061 {
11062         float projectionvector[4][3];
11063         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11064         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11065         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11066         projectionvector[0][0] = planes[0][0] * ilocalsize;
11067         projectionvector[0][1] = planes[1][0] * ilocalsize;
11068         projectionvector[0][2] = planes[2][0] * ilocalsize;
11069         projectionvector[1][0] = planes[0][1] * ilocalsize;
11070         projectionvector[1][1] = planes[1][1] * ilocalsize;
11071         projectionvector[1][2] = planes[2][1] * ilocalsize;
11072         projectionvector[2][0] = planes[0][2] * ilocalsize;
11073         projectionvector[2][1] = planes[1][2] * ilocalsize;
11074         projectionvector[2][2] = planes[2][2] * ilocalsize;
11075         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11076         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11077         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11078         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11079 }
11080 #endif
11081
11082         dynamic = model->surfmesh.isanimated;
11083         numsurfacelist = model->nummodelsurfaces;
11084         surfacelist = model->sortedmodelsurfaces;
11085         surfaces = model->data_surfaces;
11086
11087         bih = NULL;
11088         bih_triangles_count = -1;
11089         if(!dynamic)
11090         {
11091                 if(model->render_bih.numleafs)
11092                         bih = &model->render_bih;
11093                 else if(model->collision_bih.numleafs)
11094                         bih = &model->collision_bih;
11095         }
11096         if(bih)
11097                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11098         if(bih_triangles_count == 0)
11099                 return;
11100         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11101                 return;
11102         if(bih_triangles_count > 0)
11103         {
11104                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11105                 {
11106                         surfaceindex = bih_surfaces[triangleindex];
11107                         surface = surfaces + surfaceindex;
11108                         texture = surface->texture;
11109                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11110                                 continue;
11111                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11112                                 continue;
11113                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11114                 }
11115         }
11116         else
11117         {
11118                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11119                 {
11120                         surfaceindex = surfacelist[surfacelistindex];
11121                         surface = surfaces + surfaceindex;
11122                         // check cull box first because it rejects more than any other check
11123                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11124                                 continue;
11125                         // skip transparent surfaces
11126                         texture = surface->texture;
11127                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11128                                 continue;
11129                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11130                                 continue;
11131                         numtriangles = surface->num_triangles;
11132                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11133                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11134                 }
11135         }
11136 }
11137
11138 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11139 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)
11140 {
11141         int renderentityindex;
11142         float worldmins[3];
11143         float worldmaxs[3];
11144         entity_render_t *ent;
11145
11146         if (!cl_decals_newsystem.integer)
11147                 return;
11148
11149         worldmins[0] = worldorigin[0] - worldsize;
11150         worldmins[1] = worldorigin[1] - worldsize;
11151         worldmins[2] = worldorigin[2] - worldsize;
11152         worldmaxs[0] = worldorigin[0] + worldsize;
11153         worldmaxs[1] = worldorigin[1] + worldsize;
11154         worldmaxs[2] = worldorigin[2] + worldsize;
11155
11156         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11157
11158         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11159         {
11160                 ent = r_refdef.scene.entities[renderentityindex];
11161                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11162                         continue;
11163
11164                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11165         }
11166 }
11167
11168 typedef struct r_decalsystem_splatqueue_s
11169 {
11170         vec3_t worldorigin;
11171         vec3_t worldnormal;
11172         float color[4];
11173         float tcrange[4];
11174         float worldsize;
11175         int decalsequence;
11176 }
11177 r_decalsystem_splatqueue_t;
11178
11179 int r_decalsystem_numqueued = 0;
11180 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11181
11182 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)
11183 {
11184         r_decalsystem_splatqueue_t *queue;
11185
11186         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11187                 return;
11188
11189         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11190         VectorCopy(worldorigin, queue->worldorigin);
11191         VectorCopy(worldnormal, queue->worldnormal);
11192         Vector4Set(queue->color, r, g, b, a);
11193         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11194         queue->worldsize = worldsize;
11195         queue->decalsequence = cl.decalsequence++;
11196 }
11197
11198 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11199 {
11200         int i;
11201         r_decalsystem_splatqueue_t *queue;
11202
11203         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11204                 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);
11205         r_decalsystem_numqueued = 0;
11206 }
11207
11208 extern cvar_t cl_decals_max;
11209 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11210 {
11211         int i;
11212         decalsystem_t *decalsystem = &ent->decalsystem;
11213         int numdecals;
11214         int killsequence;
11215         tridecal_t *decal;
11216         float frametime;
11217         float lifetime;
11218
11219         if (!decalsystem->numdecals)
11220                 return;
11221
11222         if (r_showsurfaces.integer)
11223                 return;
11224
11225         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11226         {
11227                 R_DecalSystem_Reset(decalsystem);
11228                 return;
11229         }
11230
11231         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11232         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11233
11234         if (decalsystem->lastupdatetime)
11235                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11236         else
11237                 frametime = 0;
11238         decalsystem->lastupdatetime = r_refdef.scene.time;
11239         numdecals = decalsystem->numdecals;
11240
11241         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11242         {
11243                 if (decal->color4f[0][3])
11244                 {
11245                         decal->lived += frametime;
11246                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11247                         {
11248                                 memset(decal, 0, sizeof(*decal));
11249                                 if (decalsystem->freedecal > i)
11250                                         decalsystem->freedecal = i;
11251                         }
11252                 }
11253         }
11254         decal = decalsystem->decals;
11255         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11256                 numdecals--;
11257
11258         // collapse the array by shuffling the tail decals into the gaps
11259         for (;;)
11260         {
11261                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11262                         decalsystem->freedecal++;
11263                 if (decalsystem->freedecal == numdecals)
11264                         break;
11265                 decal[decalsystem->freedecal] = decal[--numdecals];
11266         }
11267
11268         decalsystem->numdecals = numdecals;
11269
11270         if (numdecals <= 0)
11271         {
11272                 // if there are no decals left, reset decalsystem
11273                 R_DecalSystem_Reset(decalsystem);
11274         }
11275 }
11276
11277 extern skinframe_t *decalskinframe;
11278 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11279 {
11280         int i;
11281         decalsystem_t *decalsystem = &ent->decalsystem;
11282         int numdecals;
11283         tridecal_t *decal;
11284         float faderate;
11285         float alpha;
11286         float *v3f;
11287         float *c4f;
11288         float *t2f;
11289         const int *e;
11290         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11291         int numtris = 0;
11292
11293         numdecals = decalsystem->numdecals;
11294         if (!numdecals)
11295                 return;
11296
11297         if (r_showsurfaces.integer)
11298                 return;
11299
11300         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11301         {
11302                 R_DecalSystem_Reset(decalsystem);
11303                 return;
11304         }
11305
11306         // if the model is static it doesn't matter what value we give for
11307         // wantnormals and wanttangents, so this logic uses only rules applicable
11308         // to a model, knowing that they are meaningless otherwise
11309         if (ent == r_refdef.scene.worldentity)
11310                 RSurf_ActiveWorldEntity();
11311         else
11312                 RSurf_ActiveModelEntity(ent, false, false, false);
11313
11314         decalsystem->lastupdatetime = r_refdef.scene.time;
11315
11316         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11317
11318         // update vertex positions for animated models
11319         v3f = decalsystem->vertex3f;
11320         c4f = decalsystem->color4f;
11321         t2f = decalsystem->texcoord2f;
11322         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11323         {
11324                 if (!decal->color4f[0][3])
11325                         continue;
11326
11327                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11328                         continue;
11329
11330                 // skip backfaces
11331                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11332                         continue;
11333
11334                 // update color values for fading decals
11335                 if (decal->lived >= cl_decals_time.value)
11336                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11337                 else
11338                         alpha = 1.0f;
11339
11340                 c4f[ 0] = decal->color4f[0][0] * alpha;
11341                 c4f[ 1] = decal->color4f[0][1] * alpha;
11342                 c4f[ 2] = decal->color4f[0][2] * alpha;
11343                 c4f[ 3] = 1;
11344                 c4f[ 4] = decal->color4f[1][0] * alpha;
11345                 c4f[ 5] = decal->color4f[1][1] * alpha;
11346                 c4f[ 6] = decal->color4f[1][2] * alpha;
11347                 c4f[ 7] = 1;
11348                 c4f[ 8] = decal->color4f[2][0] * alpha;
11349                 c4f[ 9] = decal->color4f[2][1] * alpha;
11350                 c4f[10] = decal->color4f[2][2] * alpha;
11351                 c4f[11] = 1;
11352
11353                 t2f[0] = decal->texcoord2f[0][0];
11354                 t2f[1] = decal->texcoord2f[0][1];
11355                 t2f[2] = decal->texcoord2f[1][0];
11356                 t2f[3] = decal->texcoord2f[1][1];
11357                 t2f[4] = decal->texcoord2f[2][0];
11358                 t2f[5] = decal->texcoord2f[2][1];
11359
11360                 // update vertex positions for animated models
11361                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11362                 {
11363                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11364                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11365                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11366                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11367                 }
11368                 else
11369                 {
11370                         VectorCopy(decal->vertex3f[0], v3f);
11371                         VectorCopy(decal->vertex3f[1], v3f + 3);
11372                         VectorCopy(decal->vertex3f[2], v3f + 6);
11373                 }
11374
11375                 if (r_refdef.fogenabled)
11376                 {
11377                         alpha = RSurf_FogVertex(v3f);
11378                         VectorScale(c4f, alpha, c4f);
11379                         alpha = RSurf_FogVertex(v3f + 3);
11380                         VectorScale(c4f + 4, alpha, c4f + 4);
11381                         alpha = RSurf_FogVertex(v3f + 6);
11382                         VectorScale(c4f + 8, alpha, c4f + 8);
11383                 }
11384
11385                 v3f += 9;
11386                 c4f += 12;
11387                 t2f += 6;
11388                 numtris++;
11389         }
11390
11391         if (numtris > 0)
11392         {
11393                 r_refdef.stats.drawndecals += numtris;
11394
11395                 // now render the decals all at once
11396                 // (this assumes they all use one particle font texture!)
11397                 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);
11398 //              R_Mesh_ResetTextureState();
11399                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11400                 GL_DepthMask(false);
11401                 GL_DepthRange(0, 1);
11402                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11403                 GL_DepthTest(true);
11404                 GL_CullFace(GL_NONE);
11405                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11406                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11407                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11408         }
11409 }
11410
11411 static void R_DrawModelDecals(void)
11412 {
11413         int i, numdecals;
11414
11415         // fade faster when there are too many decals
11416         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11417         for (i = 0;i < r_refdef.scene.numentities;i++)
11418                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11419
11420         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11421         for (i = 0;i < r_refdef.scene.numentities;i++)
11422                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11423                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11424
11425         R_DecalSystem_ApplySplatEntitiesQueue();
11426
11427         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11428         for (i = 0;i < r_refdef.scene.numentities;i++)
11429                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11430
11431         r_refdef.stats.totaldecals += numdecals;
11432
11433         if (r_showsurfaces.integer)
11434                 return;
11435
11436         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11437
11438         for (i = 0;i < r_refdef.scene.numentities;i++)
11439         {
11440                 if (!r_refdef.viewcache.entityvisible[i])
11441                         continue;
11442                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11443                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11444         }
11445 }
11446
11447 extern cvar_t mod_collision_bih;
11448 static void R_DrawDebugModel(void)
11449 {
11450         entity_render_t *ent = rsurface.entity;
11451         int i, j, k, l, flagsmask;
11452         const msurface_t *surface;
11453         dp_model_t *model = ent->model;
11454         vec3_t v;
11455
11456         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11457                 return;
11458
11459         if (r_showoverdraw.value > 0)
11460         {
11461                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11462                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11463                 R_SetupShader_Generic_NoTexture(false, false);
11464                 GL_DepthTest(false);
11465                 GL_DepthMask(false);
11466                 GL_DepthRange(0, 1);
11467                 GL_BlendFunc(GL_ONE, GL_ONE);
11468                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11469                 {
11470                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11471                                 continue;
11472                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11473                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11474                         {
11475                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11476                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11477                                 if (!rsurface.texture->currentlayers->depthmask)
11478                                         GL_Color(c, 0, 0, 1.0f);
11479                                 else if (ent == r_refdef.scene.worldentity)
11480                                         GL_Color(c, c, c, 1.0f);
11481                                 else
11482                                         GL_Color(0, c, 0, 1.0f);
11483                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11484                                 RSurf_DrawBatch();
11485                         }
11486                 }
11487                 rsurface.texture = NULL;
11488         }
11489
11490         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11491
11492 //      R_Mesh_ResetTextureState();
11493         R_SetupShader_Generic_NoTexture(false, false);
11494         GL_DepthRange(0, 1);
11495         GL_DepthTest(!r_showdisabledepthtest.integer);
11496         GL_DepthMask(false);
11497         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11498
11499         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11500         {
11501                 int triangleindex;
11502                 int bihleafindex;
11503                 qboolean cullbox = false;
11504                 const q3mbrush_t *brush;
11505                 const bih_t *bih = &model->collision_bih;
11506                 const bih_leaf_t *bihleaf;
11507                 float vertex3f[3][3];
11508                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11509                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11510                 {
11511                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11512                                 continue;
11513                         switch (bihleaf->type)
11514                         {
11515                         case BIH_BRUSH:
11516                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11517                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11518                                 {
11519                                         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);
11520                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11521                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11522                                 }
11523                                 break;
11524                         case BIH_COLLISIONTRIANGLE:
11525                                 triangleindex = bihleaf->itemindex;
11526                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11527                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11528                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11529                                 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);
11530                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11531                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11532                                 break;
11533                         case BIH_RENDERTRIANGLE:
11534                                 triangleindex = bihleaf->itemindex;
11535                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11536                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11537                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11538                                 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);
11539                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11540                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11541                                 break;
11542                         }
11543                 }
11544         }
11545
11546         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11547
11548 #ifndef USE_GLES2
11549         if (r_showtris.integer && qglPolygonMode)
11550         {
11551                 if (r_showdisabledepthtest.integer)
11552                 {
11553                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11554                         GL_DepthMask(false);
11555                 }
11556                 else
11557                 {
11558                         GL_BlendFunc(GL_ONE, GL_ZERO);
11559                         GL_DepthMask(true);
11560                 }
11561                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11562                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11563                 {
11564                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11565                                 continue;
11566                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11567                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11568                         {
11569                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11570                                 if (!rsurface.texture->currentlayers->depthmask)
11571                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11572                                 else if (ent == r_refdef.scene.worldentity)
11573                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11574                                 else
11575                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11576                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11577                                 RSurf_DrawBatch();
11578                         }
11579                 }
11580                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11581                 rsurface.texture = NULL;
11582         }
11583
11584         if (r_shownormals.value != 0 && qglBegin)
11585         {
11586                 if (r_showdisabledepthtest.integer)
11587                 {
11588                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11589                         GL_DepthMask(false);
11590                 }
11591                 else
11592                 {
11593                         GL_BlendFunc(GL_ONE, GL_ZERO);
11594                         GL_DepthMask(true);
11595                 }
11596                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11597                 {
11598                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11599                                 continue;
11600                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11601                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11602                         {
11603                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11604                                 qglBegin(GL_LINES);
11605                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11606                                 {
11607                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11608                                         {
11609                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11610                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11611                                                 qglVertex3f(v[0], v[1], v[2]);
11612                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11613                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11614                                                 qglVertex3f(v[0], v[1], v[2]);
11615                                         }
11616                                 }
11617                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11618                                 {
11619                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11620                                         {
11621                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11622                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11623                                                 qglVertex3f(v[0], v[1], v[2]);
11624                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11625                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11626                                                 qglVertex3f(v[0], v[1], v[2]);
11627                                         }
11628                                 }
11629                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11630                                 {
11631                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11632                                         {
11633                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11634                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11635                                                 qglVertex3f(v[0], v[1], v[2]);
11636                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11637                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11638                                                 qglVertex3f(v[0], v[1], v[2]);
11639                                         }
11640                                 }
11641                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11642                                 {
11643                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11644                                         {
11645                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11646                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11647                                                 qglVertex3f(v[0], v[1], v[2]);
11648                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11649                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11650                                                 qglVertex3f(v[0], v[1], v[2]);
11651                                         }
11652                                 }
11653                                 qglEnd();
11654                                 CHECKGLERROR
11655                         }
11656                 }
11657                 rsurface.texture = NULL;
11658         }
11659 #endif
11660 }
11661
11662 int r_maxsurfacelist = 0;
11663 const msurface_t **r_surfacelist = NULL;
11664 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11665 {
11666         int i, j, endj, flagsmask;
11667         dp_model_t *model = r_refdef.scene.worldmodel;
11668         msurface_t *surfaces;
11669         unsigned char *update;
11670         int numsurfacelist = 0;
11671         if (model == NULL)
11672                 return;
11673
11674         if (r_maxsurfacelist < model->num_surfaces)
11675         {
11676                 r_maxsurfacelist = model->num_surfaces;
11677                 if (r_surfacelist)
11678                         Mem_Free((msurface_t**)r_surfacelist);
11679                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11680         }
11681
11682         RSurf_ActiveWorldEntity();
11683
11684         surfaces = model->data_surfaces;
11685         update = model->brushq1.lightmapupdateflags;
11686
11687         // update light styles on this submodel
11688         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11689         {
11690                 model_brush_lightstyleinfo_t *style;
11691                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11692                 {
11693                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11694                         {
11695                                 int *list = style->surfacelist;
11696                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11697                                 for (j = 0;j < style->numsurfaces;j++)
11698                                         update[list[j]] = true;
11699                         }
11700                 }
11701         }
11702
11703         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11704
11705         if (debug)
11706         {
11707                 R_DrawDebugModel();
11708                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11709                 return;
11710         }
11711
11712         rsurface.lightmaptexture = NULL;
11713         rsurface.deluxemaptexture = NULL;
11714         rsurface.uselightmaptexture = false;
11715         rsurface.texture = NULL;
11716         rsurface.rtlight = NULL;
11717         numsurfacelist = 0;
11718         // add visible surfaces to draw list
11719         for (i = 0;i < model->nummodelsurfaces;i++)
11720         {
11721                 j = model->sortedmodelsurfaces[i];
11722                 if (r_refdef.viewcache.world_surfacevisible[j])
11723                         r_surfacelist[numsurfacelist++] = surfaces + j;
11724         }
11725         // update lightmaps if needed
11726         if (model->brushq1.firstrender)
11727         {
11728                 model->brushq1.firstrender = false;
11729                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11730                         if (update[j])
11731                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11732         }
11733         else if (update)
11734         {
11735                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11736                         if (r_refdef.viewcache.world_surfacevisible[j])
11737                                 if (update[j])
11738                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11739         }
11740         // don't do anything if there were no surfaces
11741         if (!numsurfacelist)
11742         {
11743                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11744                 return;
11745         }
11746         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11747
11748         // add to stats if desired
11749         if (r_speeds.integer && !skysurfaces && !depthonly)
11750         {
11751                 r_refdef.stats.world_surfaces += numsurfacelist;
11752                 for (j = 0;j < numsurfacelist;j++)
11753                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11754         }
11755
11756         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11757 }
11758
11759 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11760 {
11761         int i, j, endj, flagsmask;
11762         dp_model_t *model = ent->model;
11763         msurface_t *surfaces;
11764         unsigned char *update;
11765         int numsurfacelist = 0;
11766         if (model == NULL)
11767                 return;
11768
11769         if (r_maxsurfacelist < model->num_surfaces)
11770         {
11771                 r_maxsurfacelist = model->num_surfaces;
11772                 if (r_surfacelist)
11773                         Mem_Free((msurface_t **)r_surfacelist);
11774                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11775         }
11776
11777         // if the model is static it doesn't matter what value we give for
11778         // wantnormals and wanttangents, so this logic uses only rules applicable
11779         // to a model, knowing that they are meaningless otherwise
11780         if (ent == r_refdef.scene.worldentity)
11781                 RSurf_ActiveWorldEntity();
11782         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11783                 RSurf_ActiveModelEntity(ent, false, false, false);
11784         else if (prepass)
11785                 RSurf_ActiveModelEntity(ent, true, true, true);
11786         else if (depthonly)
11787         {
11788                 switch (vid.renderpath)
11789                 {
11790                 case RENDERPATH_GL20:
11791                 case RENDERPATH_D3D9:
11792                 case RENDERPATH_D3D10:
11793                 case RENDERPATH_D3D11:
11794                 case RENDERPATH_SOFT:
11795                 case RENDERPATH_GLES2:
11796                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11797                         break;
11798                 case RENDERPATH_GL11:
11799                 case RENDERPATH_GL13:
11800                 case RENDERPATH_GLES1:
11801                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11802                         break;
11803                 }
11804         }
11805         else
11806         {
11807                 switch (vid.renderpath)
11808                 {
11809                 case RENDERPATH_GL20:
11810                 case RENDERPATH_D3D9:
11811                 case RENDERPATH_D3D10:
11812                 case RENDERPATH_D3D11:
11813                 case RENDERPATH_SOFT:
11814                 case RENDERPATH_GLES2:
11815                         RSurf_ActiveModelEntity(ent, true, true, false);
11816                         break;
11817                 case RENDERPATH_GL11:
11818                 case RENDERPATH_GL13:
11819                 case RENDERPATH_GLES1:
11820                         RSurf_ActiveModelEntity(ent, true, false, false);
11821                         break;
11822                 }
11823         }
11824
11825         surfaces = model->data_surfaces;
11826         update = model->brushq1.lightmapupdateflags;
11827
11828         // update light styles
11829         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11830         {
11831                 model_brush_lightstyleinfo_t *style;
11832                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11833                 {
11834                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11835                         {
11836                                 int *list = style->surfacelist;
11837                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11838                                 for (j = 0;j < style->numsurfaces;j++)
11839                                         update[list[j]] = true;
11840                         }
11841                 }
11842         }
11843
11844         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11845
11846         if (debug)
11847         {
11848                 R_DrawDebugModel();
11849                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11850                 return;
11851         }
11852
11853         rsurface.lightmaptexture = NULL;
11854         rsurface.deluxemaptexture = NULL;
11855         rsurface.uselightmaptexture = false;
11856         rsurface.texture = NULL;
11857         rsurface.rtlight = NULL;
11858         numsurfacelist = 0;
11859         // add visible surfaces to draw list
11860         for (i = 0;i < model->nummodelsurfaces;i++)
11861                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11862         // don't do anything if there were no surfaces
11863         if (!numsurfacelist)
11864         {
11865                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11866                 return;
11867         }
11868         // update lightmaps if needed
11869         if (update)
11870         {
11871                 int updated = 0;
11872                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11873                 {
11874                         if (update[j])
11875                         {
11876                                 updated++;
11877                                 R_BuildLightMap(ent, surfaces + j);
11878                         }
11879                 }
11880         }
11881
11882         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11883
11884         // add to stats if desired
11885         if (r_speeds.integer && !skysurfaces && !depthonly)
11886         {
11887                 r_refdef.stats.entities_surfaces += numsurfacelist;
11888                 for (j = 0;j < numsurfacelist;j++)
11889                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11890         }
11891
11892         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11893 }
11894
11895 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11896 {
11897         static texture_t texture;
11898         static msurface_t surface;
11899         const msurface_t *surfacelist = &surface;
11900
11901         // fake enough texture and surface state to render this geometry
11902
11903         texture.update_lastrenderframe = -1; // regenerate this texture
11904         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11905         texture.currentskinframe = skinframe;
11906         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11907         texture.offsetmapping = OFFSETMAPPING_OFF;
11908         texture.offsetscale = 1;
11909         texture.specularscalemod = 1;
11910         texture.specularpowermod = 1;
11911         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
11912         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
11913         // JUST GREP FOR "specularscalemod = 1".
11914
11915         surface.texture = &texture;
11916         surface.num_triangles = numtriangles;
11917         surface.num_firsttriangle = firsttriangle;
11918         surface.num_vertices = numvertices;
11919         surface.num_firstvertex = firstvertex;
11920
11921         // now render it
11922         rsurface.texture = R_GetCurrentTexture(surface.texture);
11923         rsurface.lightmaptexture = NULL;
11924         rsurface.deluxemaptexture = NULL;
11925         rsurface.uselightmaptexture = false;
11926         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11927 }
11928
11929 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)
11930 {
11931         static msurface_t surface;
11932         const msurface_t *surfacelist = &surface;
11933
11934         // fake enough texture and surface state to render this geometry
11935         surface.texture = texture;
11936         surface.num_triangles = numtriangles;
11937         surface.num_firsttriangle = firsttriangle;
11938         surface.num_vertices = numvertices;
11939         surface.num_firstvertex = firstvertex;
11940
11941         // now render it
11942         rsurface.texture = R_GetCurrentTexture(surface.texture);
11943         rsurface.lightmaptexture = NULL;
11944         rsurface.deluxemaptexture = NULL;
11945         rsurface.uselightmaptexture = false;
11946         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11947 }