]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
only include SDL_syswm.h if really necessary
[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_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
229 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"};
230
231 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."};
232
233 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)"};
234
235 extern cvar_t v_glslgamma;
236 extern cvar_t v_glslgamma_2d;
237
238 extern qboolean v_flipped_state;
239
240 r_framebufferstate_t r_fb;
241
242 /// shadow volume bsp struct with automatically growing nodes buffer
243 svbsp_t r_svbsp;
244
245 rtexture_t *r_texture_blanknormalmap;
246 rtexture_t *r_texture_white;
247 rtexture_t *r_texture_grey128;
248 rtexture_t *r_texture_black;
249 rtexture_t *r_texture_notexture;
250 rtexture_t *r_texture_whitecube;
251 rtexture_t *r_texture_normalizationcube;
252 rtexture_t *r_texture_fogattenuation;
253 rtexture_t *r_texture_fogheighttexture;
254 rtexture_t *r_texture_gammaramps;
255 unsigned int r_texture_gammaramps_serial;
256 //rtexture_t *r_texture_fogintensity;
257 rtexture_t *r_texture_reflectcube;
258
259 // TODO: hash lookups?
260 typedef struct cubemapinfo_s
261 {
262         char basename[64];
263         rtexture_t *texture;
264 }
265 cubemapinfo_t;
266
267 int r_texture_numcubemaps;
268 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
269
270 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
271 unsigned int r_numqueries;
272 unsigned int r_maxqueries;
273
274 typedef struct r_qwskincache_s
275 {
276         char name[MAX_QPATH];
277         skinframe_t *skinframe;
278 }
279 r_qwskincache_t;
280
281 static r_qwskincache_t *r_qwskincache;
282 static int r_qwskincache_size;
283
284 /// vertex coordinates for a quad that covers the screen exactly
285 extern const float r_screenvertex3f[12];
286 extern const float r_d3dscreenvertex3f[12];
287 const float r_screenvertex3f[12] =
288 {
289         0, 0, 0,
290         1, 0, 0,
291         1, 1, 0,
292         0, 1, 0
293 };
294 const float r_d3dscreenvertex3f[12] =
295 {
296         0, 1, 0,
297         1, 1, 0,
298         1, 0, 0,
299         0, 0, 0
300 };
301
302 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
303 {
304         int i;
305         for (i = 0;i < verts;i++)
306         {
307                 out[0] = in[0] * r;
308                 out[1] = in[1] * g;
309                 out[2] = in[2] * b;
310                 out[3] = in[3];
311                 in += 4;
312                 out += 4;
313         }
314 }
315
316 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
317 {
318         int i;
319         for (i = 0;i < verts;i++)
320         {
321                 out[0] = r;
322                 out[1] = g;
323                 out[2] = b;
324                 out[3] = a;
325                 out += 4;
326         }
327 }
328
329 // FIXME: move this to client?
330 void FOG_clear(void)
331 {
332         if (gamemode == GAME_NEHAHRA)
333         {
334                 Cvar_Set("gl_fogenable", "0");
335                 Cvar_Set("gl_fogdensity", "0.2");
336                 Cvar_Set("gl_fogred", "0.3");
337                 Cvar_Set("gl_foggreen", "0.3");
338                 Cvar_Set("gl_fogblue", "0.3");
339         }
340         r_refdef.fog_density = 0;
341         r_refdef.fog_red = 0;
342         r_refdef.fog_green = 0;
343         r_refdef.fog_blue = 0;
344         r_refdef.fog_alpha = 1;
345         r_refdef.fog_start = 0;
346         r_refdef.fog_end = 16384;
347         r_refdef.fog_height = 1<<30;
348         r_refdef.fog_fadedepth = 128;
349         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
350 }
351
352 static void R_BuildBlankTextures(void)
353 {
354         unsigned char data[4];
355         data[2] = 128; // normal X
356         data[1] = 128; // normal Y
357         data[0] = 255; // normal Z
358         data[3] = 255; // height
359         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
360         data[0] = 255;
361         data[1] = 255;
362         data[2] = 255;
363         data[3] = 255;
364         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365         data[0] = 128;
366         data[1] = 128;
367         data[2] = 128;
368         data[3] = 255;
369         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370         data[0] = 0;
371         data[1] = 0;
372         data[2] = 0;
373         data[3] = 255;
374         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375 }
376
377 static void R_BuildNoTexture(void)
378 {
379         int x, y;
380         unsigned char pix[16][16][4];
381         // this makes a light grey/dark grey checkerboard texture
382         for (y = 0;y < 16;y++)
383         {
384                 for (x = 0;x < 16;x++)
385                 {
386                         if ((y < 8) ^ (x < 8))
387                         {
388                                 pix[y][x][0] = 128;
389                                 pix[y][x][1] = 128;
390                                 pix[y][x][2] = 128;
391                                 pix[y][x][3] = 255;
392                         }
393                         else
394                         {
395                                 pix[y][x][0] = 64;
396                                 pix[y][x][1] = 64;
397                                 pix[y][x][2] = 64;
398                                 pix[y][x][3] = 255;
399                         }
400                 }
401         }
402         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
403 }
404
405 static void R_BuildWhiteCube(void)
406 {
407         unsigned char data[6*1*1*4];
408         memset(data, 255, sizeof(data));
409         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
410 }
411
412 static void R_BuildNormalizationCube(void)
413 {
414         int x, y, side;
415         vec3_t v;
416         vec_t s, t, intensity;
417 #define NORMSIZE 64
418         unsigned char *data;
419         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
420         for (side = 0;side < 6;side++)
421         {
422                 for (y = 0;y < NORMSIZE;y++)
423                 {
424                         for (x = 0;x < NORMSIZE;x++)
425                         {
426                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
427                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
428                                 switch(side)
429                                 {
430                                 default:
431                                 case 0:
432                                         v[0] = 1;
433                                         v[1] = -t;
434                                         v[2] = -s;
435                                         break;
436                                 case 1:
437                                         v[0] = -1;
438                                         v[1] = -t;
439                                         v[2] = s;
440                                         break;
441                                 case 2:
442                                         v[0] = s;
443                                         v[1] = 1;
444                                         v[2] = t;
445                                         break;
446                                 case 3:
447                                         v[0] = s;
448                                         v[1] = -1;
449                                         v[2] = -t;
450                                         break;
451                                 case 4:
452                                         v[0] = s;
453                                         v[1] = -t;
454                                         v[2] = 1;
455                                         break;
456                                 case 5:
457                                         v[0] = -s;
458                                         v[1] = -t;
459                                         v[2] = -1;
460                                         break;
461                                 }
462                                 intensity = 127.0f / sqrt(DotProduct(v, v));
463                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
464                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
465                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
466                                 data[((side*64+y)*64+x)*4+3] = 255;
467                         }
468                 }
469         }
470         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
471         Mem_Free(data);
472 }
473
474 static void R_BuildFogTexture(void)
475 {
476         int x, b;
477 #define FOGWIDTH 256
478         unsigned char data1[FOGWIDTH][4];
479         //unsigned char data2[FOGWIDTH][4];
480         double d, r, alpha;
481
482         r_refdef.fogmasktable_start = r_refdef.fog_start;
483         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
484         r_refdef.fogmasktable_range = r_refdef.fogrange;
485         r_refdef.fogmasktable_density = r_refdef.fog_density;
486
487         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
488         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
489         {
490                 d = (x * r - r_refdef.fogmasktable_start);
491                 if(developer_extra.integer)
492                         Con_DPrintf("%f ", d);
493                 d = max(0, d);
494                 if (r_fog_exp2.integer)
495                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
496                 else
497                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
498                 if(developer_extra.integer)
499                         Con_DPrintf(" : %f ", alpha);
500                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
501                 if(developer_extra.integer)
502                         Con_DPrintf(" = %f\n", alpha);
503                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
504         }
505
506         for (x = 0;x < FOGWIDTH;x++)
507         {
508                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
509                 data1[x][0] = b;
510                 data1[x][1] = b;
511                 data1[x][2] = b;
512                 data1[x][3] = 255;
513                 //data2[x][0] = 255 - b;
514                 //data2[x][1] = 255 - b;
515                 //data2[x][2] = 255 - b;
516                 //data2[x][3] = 255;
517         }
518         if (r_texture_fogattenuation)
519         {
520                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
521                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
522         }
523         else
524         {
525                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
526                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
527         }
528 }
529
530 static void R_BuildFogHeightTexture(void)
531 {
532         unsigned char *inpixels;
533         int size;
534         int x;
535         int y;
536         int j;
537         float c[4];
538         float f;
539         inpixels = NULL;
540         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
541         if (r_refdef.fogheighttexturename[0])
542                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
543         if (!inpixels)
544         {
545                 r_refdef.fog_height_tablesize = 0;
546                 if (r_texture_fogheighttexture)
547                         R_FreeTexture(r_texture_fogheighttexture);
548                 r_texture_fogheighttexture = NULL;
549                 if (r_refdef.fog_height_table2d)
550                         Mem_Free(r_refdef.fog_height_table2d);
551                 r_refdef.fog_height_table2d = NULL;
552                 if (r_refdef.fog_height_table1d)
553                         Mem_Free(r_refdef.fog_height_table1d);
554                 r_refdef.fog_height_table1d = NULL;
555                 return;
556         }
557         size = image_width;
558         r_refdef.fog_height_tablesize = size;
559         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
560         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
561         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
562         Mem_Free(inpixels);
563         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
564         // average fog color table accounting for every fog layer between a point
565         // and the camera.  (Note: attenuation is handled separately!)
566         for (y = 0;y < size;y++)
567         {
568                 for (x = 0;x < size;x++)
569                 {
570                         Vector4Clear(c);
571                         f = 0;
572                         if (x < y)
573                         {
574                                 for (j = x;j <= y;j++)
575                                 {
576                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
577                                         f++;
578                                 }
579                         }
580                         else
581                         {
582                                 for (j = x;j >= y;j--)
583                                 {
584                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
585                                         f++;
586                                 }
587                         }
588                         f = 1.0f / f;
589                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
590                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
591                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
592                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
593                 }
594         }
595         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
596 }
597
598 //=======================================================================================================================================================
599
600 static const char *builtinshaderstring =
601 #include "shader_glsl.h"
602 ;
603
604 const char *builtinhlslshaderstring =
605 #include "shader_hlsl.h"
606 ;
607
608 char *glslshaderstring = NULL;
609 char *hlslshaderstring = NULL;
610
611 //=======================================================================================================================================================
612
613 typedef struct shaderpermutationinfo_s
614 {
615         const char *pretext;
616         const char *name;
617 }
618 shaderpermutationinfo_t;
619
620 typedef struct shadermodeinfo_s
621 {
622         const char *vertexfilename;
623         const char *geometryfilename;
624         const char *fragmentfilename;
625         const char *pretext;
626         const char *name;
627 }
628 shadermodeinfo_t;
629
630 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
631 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
632 {
633         {"#define USEDIFFUSE\n", " diffuse"},
634         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
635         {"#define USEVIEWTINT\n", " viewtint"},
636         {"#define USECOLORMAPPING\n", " colormapping"},
637         {"#define USESATURATION\n", " saturation"},
638         {"#define USEFOGINSIDE\n", " foginside"},
639         {"#define USEFOGOUTSIDE\n", " fogoutside"},
640         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
641         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
642         {"#define USEGAMMARAMPS\n", " gammaramps"},
643         {"#define USECUBEFILTER\n", " cubefilter"},
644         {"#define USEGLOW\n", " glow"},
645         {"#define USEBLOOM\n", " bloom"},
646         {"#define USESPECULAR\n", " specular"},
647         {"#define USEPOSTPROCESSING\n", " postprocessing"},
648         {"#define USEREFLECTION\n", " reflection"},
649         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
650         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
651         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
652         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
653         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
654         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
655         {"#define USEALPHAKILL\n", " alphakill"},
656         {"#define USEREFLECTCUBE\n", " reflectcube"},
657         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
658         {"#define USEBOUNCEGRID\n", " bouncegrid"},
659         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
660         {"#define USETRIPPY\n", " trippy"},
661         {"#define USEDEPTHRGB\n", " depthrgb"},
662         {"#define USEALPHAGENVERTEX\n", "alphagenvertex"}
663 };
664
665 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
666 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
667 {
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
686 };
687
688 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
689 {
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
708 };
709
710 struct r_glsl_permutation_s;
711 typedef struct r_glsl_permutation_s
712 {
713         /// hash lookup data
714         struct r_glsl_permutation_s *hashnext;
715         unsigned int mode;
716         unsigned int permutation;
717
718         /// indicates if we have tried compiling this permutation already
719         qboolean compiled;
720         /// 0 if compilation failed
721         int program;
722         // texture units assigned to each detected uniform
723         int tex_Texture_First;
724         int tex_Texture_Second;
725         int tex_Texture_GammaRamps;
726         int tex_Texture_Normal;
727         int tex_Texture_Color;
728         int tex_Texture_Gloss;
729         int tex_Texture_Glow;
730         int tex_Texture_SecondaryNormal;
731         int tex_Texture_SecondaryColor;
732         int tex_Texture_SecondaryGloss;
733         int tex_Texture_SecondaryGlow;
734         int tex_Texture_Pants;
735         int tex_Texture_Shirt;
736         int tex_Texture_FogHeightTexture;
737         int tex_Texture_FogMask;
738         int tex_Texture_Lightmap;
739         int tex_Texture_Deluxemap;
740         int tex_Texture_Attenuation;
741         int tex_Texture_Cube;
742         int tex_Texture_Refraction;
743         int tex_Texture_Reflection;
744         int tex_Texture_ShadowMap2D;
745         int tex_Texture_CubeProjection;
746         int tex_Texture_ScreenNormalMap;
747         int tex_Texture_ScreenDiffuse;
748         int tex_Texture_ScreenSpecular;
749         int tex_Texture_ReflectMask;
750         int tex_Texture_ReflectCube;
751         int tex_Texture_BounceGrid;
752         /// locations of detected uniforms in program object, or -1 if not found
753         int loc_Texture_First;
754         int loc_Texture_Second;
755         int loc_Texture_GammaRamps;
756         int loc_Texture_Normal;
757         int loc_Texture_Color;
758         int loc_Texture_Gloss;
759         int loc_Texture_Glow;
760         int loc_Texture_SecondaryNormal;
761         int loc_Texture_SecondaryColor;
762         int loc_Texture_SecondaryGloss;
763         int loc_Texture_SecondaryGlow;
764         int loc_Texture_Pants;
765         int loc_Texture_Shirt;
766         int loc_Texture_FogHeightTexture;
767         int loc_Texture_FogMask;
768         int loc_Texture_Lightmap;
769         int loc_Texture_Deluxemap;
770         int loc_Texture_Attenuation;
771         int loc_Texture_Cube;
772         int loc_Texture_Refraction;
773         int loc_Texture_Reflection;
774         int loc_Texture_ShadowMap2D;
775         int loc_Texture_CubeProjection;
776         int loc_Texture_ScreenNormalMap;
777         int loc_Texture_ScreenDiffuse;
778         int loc_Texture_ScreenSpecular;
779         int loc_Texture_ReflectMask;
780         int loc_Texture_ReflectCube;
781         int loc_Texture_BounceGrid;
782         int loc_Alpha;
783         int loc_BloomBlur_Parameters;
784         int loc_ClientTime;
785         int loc_Color_Ambient;
786         int loc_Color_Diffuse;
787         int loc_Color_Specular;
788         int loc_Color_Glow;
789         int loc_Color_Pants;
790         int loc_Color_Shirt;
791         int loc_DeferredColor_Ambient;
792         int loc_DeferredColor_Diffuse;
793         int loc_DeferredColor_Specular;
794         int loc_DeferredMod_Diffuse;
795         int loc_DeferredMod_Specular;
796         int loc_DistortScaleRefractReflect;
797         int loc_EyePosition;
798         int loc_FogColor;
799         int loc_FogHeightFade;
800         int loc_FogPlane;
801         int loc_FogPlaneViewDist;
802         int loc_FogRangeRecip;
803         int loc_LightColor;
804         int loc_LightDir;
805         int loc_LightPosition;
806         int loc_OffsetMapping_ScaleSteps;
807         int loc_OffsetMapping_LodDistance;
808         int loc_OffsetMapping_Bias;
809         int loc_PixelSize;
810         int loc_ReflectColor;
811         int loc_ReflectFactor;
812         int loc_ReflectOffset;
813         int loc_RefractColor;
814         int loc_Saturation;
815         int loc_ScreenCenterRefractReflect;
816         int loc_ScreenScaleRefractReflect;
817         int loc_ScreenToDepth;
818         int loc_ShadowMap_Parameters;
819         int loc_ShadowMap_TextureScale;
820         int loc_SpecularPower;
821         int loc_UserVec1;
822         int loc_UserVec2;
823         int loc_UserVec3;
824         int loc_UserVec4;
825         int loc_ViewTintColor;
826         int loc_ViewToLight;
827         int loc_ModelToLight;
828         int loc_TexMatrix;
829         int loc_BackgroundTexMatrix;
830         int loc_ModelViewProjectionMatrix;
831         int loc_ModelViewMatrix;
832         int loc_PixelToScreenTexCoord;
833         int loc_ModelToReflectCube;
834         int loc_ShadowMapMatrix;
835         int loc_BloomColorSubtract;
836         int loc_NormalmapScrollBlend;
837         int loc_BounceGridMatrix;
838         int loc_BounceGridIntensity;
839 }
840 r_glsl_permutation_t;
841
842 #define SHADERPERMUTATION_HASHSIZE 256
843
844
845 // non-degradable "lightweight" shader parameters to keep the permutations simpler
846 // these can NOT degrade! only use for simple stuff
847 enum
848 {
849         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
850         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
851         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
852         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
853         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
854         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
855         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
856         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
857         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
858         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
859         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
860         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
861         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
862 };
863 #define SHADERSTATICPARMS_COUNT 13
864
865 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
866 static int shaderstaticparms_count = 0;
867
868 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
869 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
870
871 extern qboolean r_shadow_shadowmapsampler;
872 extern int r_shadow_shadowmappcf;
873 qboolean R_CompileShader_CheckStaticParms(void)
874 {
875         static int r_compileshader_staticparms_save[1];
876         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
877         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
878
879         // detect all
880         if (r_glsl_saturation_redcompensate.integer)
881                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
882         if (r_glsl_vertextextureblend_usebothalphas.integer)
883                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
884         if (r_shadow_glossexact.integer)
885                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
886         if (r_glsl_postprocess.integer)
887         {
888                 if (r_glsl_postprocess_uservec1_enable.integer)
889                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
890                 if (r_glsl_postprocess_uservec2_enable.integer)
891                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
892                 if (r_glsl_postprocess_uservec3_enable.integer)
893                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
894                 if (r_glsl_postprocess_uservec4_enable.integer)
895                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
896         }
897         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
898                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
899
900         if (r_shadow_shadowmapsampler)
901                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
902         if (r_shadow_shadowmappcf > 1)
903                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
904         else if (r_shadow_shadowmappcf)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
906         if (r_celshading.integer)
907                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
908         if (r_celoutlines.integer)
909                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
910
911         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
912 }
913
914 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
915         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
916                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
917         else \
918                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
919 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
920 {
921         shaderstaticparms_count = 0;
922
923         // emit all
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
925         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
926         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
936         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
937 }
938
939 /// information about each possible shader permutation
940 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
941 /// currently selected permutation
942 r_glsl_permutation_t *r_glsl_permutation;
943 /// storage for permutations linked in the hash table
944 memexpandablearray_t r_glsl_permutationarray;
945
946 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
947 {
948         //unsigned int hashdepth = 0;
949         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
950         r_glsl_permutation_t *p;
951         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
952         {
953                 if (p->mode == mode && p->permutation == permutation)
954                 {
955                         //if (hashdepth > 10)
956                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
957                         return p;
958                 }
959                 //hashdepth++;
960         }
961         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
962         p->mode = mode;
963         p->permutation = permutation;
964         p->hashnext = r_glsl_permutationhash[mode][hashindex];
965         r_glsl_permutationhash[mode][hashindex] = p;
966         //if (hashdepth > 10)
967         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
968         return p;
969 }
970
971 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
972 {
973         char *shaderstring;
974         if (!filename || !filename[0])
975                 return NULL;
976         if (!strcmp(filename, "glsl/default.glsl"))
977         {
978                 if (!glslshaderstring)
979                 {
980                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
981                         if (glslshaderstring)
982                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
983                         else
984                                 glslshaderstring = (char *)builtinshaderstring;
985                 }
986                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
987                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
988                 return shaderstring;
989         }
990         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
991         if (shaderstring)
992         {
993                 if (printfromdisknotice)
994                         Con_DPrintf("from disk %s... ", filename);
995                 return shaderstring;
996         }
997         return shaderstring;
998 }
999
1000 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1001 {
1002         int i;
1003         int sampler;
1004         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1005         char *vertexstring, *geometrystring, *fragmentstring;
1006         char permutationname[256];
1007         int vertstrings_count = 0;
1008         int geomstrings_count = 0;
1009         int fragstrings_count = 0;
1010         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1011         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1012         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1013
1014         if (p->compiled)
1015                 return;
1016         p->compiled = true;
1017         p->program = 0;
1018
1019         permutationname[0] = 0;
1020         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1021         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1022         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1023
1024         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1025
1026         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1027         if(vid.support.gl20shaders130)
1028         {
1029                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1030                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1031                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1032                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1033                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1034                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1035         }
1036
1037         // the first pretext is which type of shader to compile as
1038         // (later these will all be bound together as a program object)
1039         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1040         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1041         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1042
1043         // the second pretext is the mode (for example a light source)
1044         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1045         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1046         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1047         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1048
1049         // now add all the permutation pretexts
1050         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1051         {
1052                 if (permutation & (1<<i))
1053                 {
1054                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1055                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1056                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1057                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1058                 }
1059                 else
1060                 {
1061                         // keep line numbers correct
1062                         vertstrings_list[vertstrings_count++] = "\n";
1063                         geomstrings_list[geomstrings_count++] = "\n";
1064                         fragstrings_list[fragstrings_count++] = "\n";
1065                 }
1066         }
1067
1068         // add static parms
1069         R_CompileShader_AddStaticParms(mode, permutation);
1070         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1071         vertstrings_count += shaderstaticparms_count;
1072         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1073         geomstrings_count += shaderstaticparms_count;
1074         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1075         fragstrings_count += shaderstaticparms_count;
1076
1077         // now append the shader text itself
1078         vertstrings_list[vertstrings_count++] = vertexstring;
1079         geomstrings_list[geomstrings_count++] = geometrystring;
1080         fragstrings_list[fragstrings_count++] = fragmentstring;
1081
1082         // if any sources were NULL, clear the respective list
1083         if (!vertexstring)
1084                 vertstrings_count = 0;
1085         if (!geometrystring)
1086                 geomstrings_count = 0;
1087         if (!fragmentstring)
1088                 fragstrings_count = 0;
1089
1090         // compile the shader program
1091         if (vertstrings_count + geomstrings_count + fragstrings_count)
1092                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1093         if (p->program)
1094         {
1095                 CHECKGLERROR
1096                 qglUseProgram(p->program);CHECKGLERROR
1097                 // look up all the uniform variable names we care about, so we don't
1098                 // have to look them up every time we set them
1099
1100                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1101                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1102                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1103                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1104                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1105                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1106                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1107                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1108                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1109                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1110                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1111                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1112                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1113                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1114                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1115                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1116                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1117                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1118                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1119                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1120                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1121                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1122                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1123                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1124                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1125                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1126                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1127                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1128                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1129                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1130                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1131                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1132                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1133                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1134                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1135                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1136                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1137                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1138                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1139                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1140                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1141                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1142                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1143                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1144                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1145                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1146                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1147                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1148                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1149                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1150                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1151                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1152                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1153                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1154                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1155                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1156                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1157                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1158                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1159                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1160                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1161                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1162                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1163                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1164                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1165                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1166                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1167                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1168                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1169                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1170                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1171                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1172                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1173                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1174                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1175                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1176                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1177                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1178                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1179                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1180                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1181                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1182                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1183                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1184                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1185                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1186                 // initialize the samplers to refer to the texture units we use
1187                 p->tex_Texture_First = -1;
1188                 p->tex_Texture_Second = -1;
1189                 p->tex_Texture_GammaRamps = -1;
1190                 p->tex_Texture_Normal = -1;
1191                 p->tex_Texture_Color = -1;
1192                 p->tex_Texture_Gloss = -1;
1193                 p->tex_Texture_Glow = -1;
1194                 p->tex_Texture_SecondaryNormal = -1;
1195                 p->tex_Texture_SecondaryColor = -1;
1196                 p->tex_Texture_SecondaryGloss = -1;
1197                 p->tex_Texture_SecondaryGlow = -1;
1198                 p->tex_Texture_Pants = -1;
1199                 p->tex_Texture_Shirt = -1;
1200                 p->tex_Texture_FogHeightTexture = -1;
1201                 p->tex_Texture_FogMask = -1;
1202                 p->tex_Texture_Lightmap = -1;
1203                 p->tex_Texture_Deluxemap = -1;
1204                 p->tex_Texture_Attenuation = -1;
1205                 p->tex_Texture_Cube = -1;
1206                 p->tex_Texture_Refraction = -1;
1207                 p->tex_Texture_Reflection = -1;
1208                 p->tex_Texture_ShadowMap2D = -1;
1209                 p->tex_Texture_CubeProjection = -1;
1210                 p->tex_Texture_ScreenNormalMap = -1;
1211                 p->tex_Texture_ScreenDiffuse = -1;
1212                 p->tex_Texture_ScreenSpecular = -1;
1213                 p->tex_Texture_ReflectMask = -1;
1214                 p->tex_Texture_ReflectCube = -1;
1215                 p->tex_Texture_BounceGrid = -1;
1216                 sampler = 0;
1217                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1218                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1219                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1220                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1221                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1222                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1223                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1224                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1225                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1226                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1227                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1228                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1229                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1230                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1231                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1232                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1233                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1234                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1235                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1236                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1237                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1238                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1239                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1240                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1241                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1242                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1243                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1244                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1245                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1246                 CHECKGLERROR
1247                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1248         }
1249         else
1250                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1251
1252         // free the strings
1253         if (vertexstring)
1254                 Mem_Free(vertexstring);
1255         if (geometrystring)
1256                 Mem_Free(geometrystring);
1257         if (fragmentstring)
1258                 Mem_Free(fragmentstring);
1259 }
1260
1261 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1262 {
1263         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1264         if (r_glsl_permutation != perm)
1265         {
1266                 r_glsl_permutation = perm;
1267                 if (!r_glsl_permutation->program)
1268                 {
1269                         if (!r_glsl_permutation->compiled)
1270                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1271                         if (!r_glsl_permutation->program)
1272                         {
1273                                 // remove features until we find a valid permutation
1274                                 int i;
1275                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1276                                 {
1277                                         // reduce i more quickly whenever it would not remove any bits
1278                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1279                                         if (!(permutation & j))
1280                                                 continue;
1281                                         permutation -= j;
1282                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1283                                         if (!r_glsl_permutation->compiled)
1284                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1285                                         if (r_glsl_permutation->program)
1286                                                 break;
1287                                 }
1288                                 if (i >= SHADERPERMUTATION_COUNT)
1289                                 {
1290                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1291                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1292                                         qglUseProgram(0);CHECKGLERROR
1293                                         return; // no bit left to clear, entire mode is broken
1294                                 }
1295                         }
1296                 }
1297                 CHECKGLERROR
1298                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1299         }
1300         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1301         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1302         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1303 }
1304
1305 #ifdef SUPPORTD3D
1306
1307 #ifdef SUPPORTD3D
1308 #include <d3d9.h>
1309 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1310 extern D3DCAPS9 vid_d3d9caps;
1311 #endif
1312
1313 struct r_hlsl_permutation_s;
1314 typedef struct r_hlsl_permutation_s
1315 {
1316         /// hash lookup data
1317         struct r_hlsl_permutation_s *hashnext;
1318         unsigned int mode;
1319         unsigned int permutation;
1320
1321         /// indicates if we have tried compiling this permutation already
1322         qboolean compiled;
1323         /// NULL if compilation failed
1324         IDirect3DVertexShader9 *vertexshader;
1325         IDirect3DPixelShader9 *pixelshader;
1326 }
1327 r_hlsl_permutation_t;
1328
1329 typedef enum D3DVSREGISTER_e
1330 {
1331         D3DVSREGISTER_TexMatrix = 0, // float4x4
1332         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1333         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1334         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1335         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1336         D3DVSREGISTER_ModelToLight = 20, // float4x4
1337         D3DVSREGISTER_EyePosition = 24,
1338         D3DVSREGISTER_FogPlane = 25,
1339         D3DVSREGISTER_LightDir = 26,
1340         D3DVSREGISTER_LightPosition = 27,
1341 }
1342 D3DVSREGISTER_t;
1343
1344 typedef enum D3DPSREGISTER_e
1345 {
1346         D3DPSREGISTER_Alpha = 0,
1347         D3DPSREGISTER_BloomBlur_Parameters = 1,
1348         D3DPSREGISTER_ClientTime = 2,
1349         D3DPSREGISTER_Color_Ambient = 3,
1350         D3DPSREGISTER_Color_Diffuse = 4,
1351         D3DPSREGISTER_Color_Specular = 5,
1352         D3DPSREGISTER_Color_Glow = 6,
1353         D3DPSREGISTER_Color_Pants = 7,
1354         D3DPSREGISTER_Color_Shirt = 8,
1355         D3DPSREGISTER_DeferredColor_Ambient = 9,
1356         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1357         D3DPSREGISTER_DeferredColor_Specular = 11,
1358         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1359         D3DPSREGISTER_DeferredMod_Specular = 13,
1360         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1361         D3DPSREGISTER_EyePosition = 15, // unused
1362         D3DPSREGISTER_FogColor = 16,
1363         D3DPSREGISTER_FogHeightFade = 17,
1364         D3DPSREGISTER_FogPlane = 18,
1365         D3DPSREGISTER_FogPlaneViewDist = 19,
1366         D3DPSREGISTER_FogRangeRecip = 20,
1367         D3DPSREGISTER_LightColor = 21,
1368         D3DPSREGISTER_LightDir = 22, // unused
1369         D3DPSREGISTER_LightPosition = 23,
1370         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1371         D3DPSREGISTER_PixelSize = 25,
1372         D3DPSREGISTER_ReflectColor = 26,
1373         D3DPSREGISTER_ReflectFactor = 27,
1374         D3DPSREGISTER_ReflectOffset = 28,
1375         D3DPSREGISTER_RefractColor = 29,
1376         D3DPSREGISTER_Saturation = 30,
1377         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1378         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1379         D3DPSREGISTER_ScreenToDepth = 33,
1380         D3DPSREGISTER_ShadowMap_Parameters = 34,
1381         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1382         D3DPSREGISTER_SpecularPower = 36,
1383         D3DPSREGISTER_UserVec1 = 37,
1384         D3DPSREGISTER_UserVec2 = 38,
1385         D3DPSREGISTER_UserVec3 = 39,
1386         D3DPSREGISTER_UserVec4 = 40,
1387         D3DPSREGISTER_ViewTintColor = 41,
1388         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1389         D3DPSREGISTER_BloomColorSubtract = 43,
1390         D3DPSREGISTER_ViewToLight = 44, // float4x4
1391         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1392         D3DPSREGISTER_NormalmapScrollBlend = 52,
1393         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1394         D3DPSREGISTER_OffsetMapping_Bias = 54,
1395         // next at 54
1396 }
1397 D3DPSREGISTER_t;
1398
1399 /// information about each possible shader permutation
1400 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1401 /// currently selected permutation
1402 r_hlsl_permutation_t *r_hlsl_permutation;
1403 /// storage for permutations linked in the hash table
1404 memexpandablearray_t r_hlsl_permutationarray;
1405
1406 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1407 {
1408         //unsigned int hashdepth = 0;
1409         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1410         r_hlsl_permutation_t *p;
1411         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1412         {
1413                 if (p->mode == mode && p->permutation == permutation)
1414                 {
1415                         //if (hashdepth > 10)
1416                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1417                         return p;
1418                 }
1419                 //hashdepth++;
1420         }
1421         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1422         p->mode = mode;
1423         p->permutation = permutation;
1424         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1425         r_hlsl_permutationhash[mode][hashindex] = p;
1426         //if (hashdepth > 10)
1427         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1428         return p;
1429 }
1430
1431 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1432 {
1433         char *shaderstring;
1434         if (!filename || !filename[0])
1435                 return NULL;
1436         if (!strcmp(filename, "hlsl/default.hlsl"))
1437         {
1438                 if (!hlslshaderstring)
1439                 {
1440                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1441                         if (hlslshaderstring)
1442                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1443                         else
1444                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1445                 }
1446                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1447                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1448                 return shaderstring;
1449         }
1450         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1451         if (shaderstring)
1452         {
1453                 if (printfromdisknotice)
1454                         Con_DPrintf("from disk %s... ", filename);
1455                 return shaderstring;
1456         }
1457         return shaderstring;
1458 }
1459
1460 #include <d3dx9.h>
1461 //#include <d3dx9shader.h>
1462 //#include <d3dx9mesh.h>
1463
1464 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1465 {
1466         DWORD *vsbin = NULL;
1467         DWORD *psbin = NULL;
1468         fs_offset_t vsbinsize;
1469         fs_offset_t psbinsize;
1470 //      IDirect3DVertexShader9 *vs = NULL;
1471 //      IDirect3DPixelShader9 *ps = NULL;
1472         ID3DXBuffer *vslog = NULL;
1473         ID3DXBuffer *vsbuffer = NULL;
1474         ID3DXConstantTable *vsconstanttable = NULL;
1475         ID3DXBuffer *pslog = NULL;
1476         ID3DXBuffer *psbuffer = NULL;
1477         ID3DXConstantTable *psconstanttable = NULL;
1478         int vsresult = 0;
1479         int psresult = 0;
1480         char temp[MAX_INPUTLINE];
1481         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1482         char vabuf[1024];
1483         qboolean debugshader = gl_paranoid.integer != 0;
1484         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1485         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1486         if (!debugshader)
1487         {
1488                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1489                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1490         }
1491         if ((!vsbin && vertstring) || (!psbin && fragstring))
1492         {
1493                 const char* dllnames_d3dx9 [] =
1494                 {
1495                         "d3dx9_43.dll",
1496                         "d3dx9_42.dll",
1497                         "d3dx9_41.dll",
1498                         "d3dx9_40.dll",
1499                         "d3dx9_39.dll",
1500                         "d3dx9_38.dll",
1501                         "d3dx9_37.dll",
1502                         "d3dx9_36.dll",
1503                         "d3dx9_35.dll",
1504                         "d3dx9_34.dll",
1505                         "d3dx9_33.dll",
1506                         "d3dx9_32.dll",
1507                         "d3dx9_31.dll",
1508                         "d3dx9_30.dll",
1509                         "d3dx9_29.dll",
1510                         "d3dx9_28.dll",
1511                         "d3dx9_27.dll",
1512                         "d3dx9_26.dll",
1513                         "d3dx9_25.dll",
1514                         "d3dx9_24.dll",
1515                         NULL
1516                 };
1517                 dllhandle_t d3dx9_dll = NULL;
1518                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1519                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1520                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1521                 dllfunction_t d3dx9_dllfuncs[] =
1522                 {
1523                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1524                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1525                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1526                         {NULL, NULL}
1527                 };
1528                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1529                 {
1530                         DWORD shaderflags = 0;
1531                         if (debugshader)
1532                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1533                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1534                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1535                         if (vertstring && vertstring[0])
1536                         {
1537                                 if (debugshader)
1538                                 {
1539 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1540 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1541                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1542                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1543                                 }
1544                                 else
1545                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1546                                 if (vsbuffer)
1547                                 {
1548                                         vsbinsize = vsbuffer->GetBufferSize();
1549                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1550                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1551                                         vsbuffer->Release();
1552                                 }
1553                                 if (vslog)
1554                                 {
1555                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1556                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1557                                         vslog->Release();
1558                                 }
1559                         }
1560                         if (fragstring && fragstring[0])
1561                         {
1562                                 if (debugshader)
1563                                 {
1564 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1565 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1566                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1567                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1568                                 }
1569                                 else
1570                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1571                                 if (psbuffer)
1572                                 {
1573                                         psbinsize = psbuffer->GetBufferSize();
1574                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1575                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1576                                         psbuffer->Release();
1577                                 }
1578                                 if (pslog)
1579                                 {
1580                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1581                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1582                                         pslog->Release();
1583                                 }
1584                         }
1585                         Sys_UnloadLibrary(&d3dx9_dll);
1586                 }
1587                 else
1588                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1589         }
1590         if (vsbin && psbin)
1591         {
1592                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1593                 if (FAILED(vsresult))
1594                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1595                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1596                 if (FAILED(psresult))
1597                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1598         }
1599         // free the shader data
1600         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1601         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1602 }
1603
1604 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1605 {
1606         int i;
1607         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1608         int vertstring_length = 0;
1609         int geomstring_length = 0;
1610         int fragstring_length = 0;
1611         char *t;
1612         char *vertexstring, *geometrystring, *fragmentstring;
1613         char *vertstring, *geomstring, *fragstring;
1614         char permutationname[256];
1615         char cachename[256];
1616         int vertstrings_count = 0;
1617         int geomstrings_count = 0;
1618         int fragstrings_count = 0;
1619         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1620         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1621         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1622
1623         if (p->compiled)
1624                 return;
1625         p->compiled = true;
1626         p->vertexshader = NULL;
1627         p->pixelshader = NULL;
1628
1629         permutationname[0] = 0;
1630         cachename[0] = 0;
1631         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1632         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1633         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1634
1635         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1636         strlcat(cachename, "hlsl/", sizeof(cachename));
1637
1638         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1639         vertstrings_count = 0;
1640         geomstrings_count = 0;
1641         fragstrings_count = 0;
1642         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1643         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1644         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1645
1646         // the first pretext is which type of shader to compile as
1647         // (later these will all be bound together as a program object)
1648         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1649         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1650         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1651
1652         // the second pretext is the mode (for example a light source)
1653         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1654         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1655         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1656         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1657         strlcat(cachename, modeinfo->name, sizeof(cachename));
1658
1659         // now add all the permutation pretexts
1660         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1661         {
1662                 if (permutation & (1<<i))
1663                 {
1664                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1665                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1666                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1667                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1668                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1669                 }
1670                 else
1671                 {
1672                         // keep line numbers correct
1673                         vertstrings_list[vertstrings_count++] = "\n";
1674                         geomstrings_list[geomstrings_count++] = "\n";
1675                         fragstrings_list[fragstrings_count++] = "\n";
1676                 }
1677         }
1678
1679         // add static parms
1680         R_CompileShader_AddStaticParms(mode, permutation);
1681         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1682         vertstrings_count += shaderstaticparms_count;
1683         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1684         geomstrings_count += shaderstaticparms_count;
1685         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1686         fragstrings_count += shaderstaticparms_count;
1687
1688         // replace spaces in the cachename with _ characters
1689         for (i = 0;cachename[i];i++)
1690                 if (cachename[i] == ' ')
1691                         cachename[i] = '_';
1692
1693         // now append the shader text itself
1694         vertstrings_list[vertstrings_count++] = vertexstring;
1695         geomstrings_list[geomstrings_count++] = geometrystring;
1696         fragstrings_list[fragstrings_count++] = fragmentstring;
1697
1698         // if any sources were NULL, clear the respective list
1699         if (!vertexstring)
1700                 vertstrings_count = 0;
1701         if (!geometrystring)
1702                 geomstrings_count = 0;
1703         if (!fragmentstring)
1704                 fragstrings_count = 0;
1705
1706         vertstring_length = 0;
1707         for (i = 0;i < vertstrings_count;i++)
1708                 vertstring_length += strlen(vertstrings_list[i]);
1709         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1710         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1711                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1712
1713         geomstring_length = 0;
1714         for (i = 0;i < geomstrings_count;i++)
1715                 geomstring_length += strlen(geomstrings_list[i]);
1716         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1717         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1718                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1719
1720         fragstring_length = 0;
1721         for (i = 0;i < fragstrings_count;i++)
1722                 fragstring_length += strlen(fragstrings_list[i]);
1723         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1724         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1725                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1726
1727         // try to load the cached shader, or generate one
1728         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1729
1730         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1731                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1732         else
1733                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1734
1735         // free the strings
1736         if (vertstring)
1737                 Mem_Free(vertstring);
1738         if (geomstring)
1739                 Mem_Free(geomstring);
1740         if (fragstring)
1741                 Mem_Free(fragstring);
1742         if (vertexstring)
1743                 Mem_Free(vertexstring);
1744         if (geometrystring)
1745                 Mem_Free(geometrystring);
1746         if (fragmentstring)
1747                 Mem_Free(fragmentstring);
1748 }
1749
1750 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1751 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1752 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);}
1753 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);}
1754 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);}
1755 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);}
1756
1757 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1758 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1759 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);}
1760 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);}
1761 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);}
1762 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);}
1763
1764 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1765 {
1766         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1767         if (r_hlsl_permutation != perm)
1768         {
1769                 r_hlsl_permutation = perm;
1770                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1771                 {
1772                         if (!r_hlsl_permutation->compiled)
1773                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1774                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1775                         {
1776                                 // remove features until we find a valid permutation
1777                                 int i;
1778                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1779                                 {
1780                                         // reduce i more quickly whenever it would not remove any bits
1781                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1782                                         if (!(permutation & j))
1783                                                 continue;
1784                                         permutation -= j;
1785                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1786                                         if (!r_hlsl_permutation->compiled)
1787                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1788                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1789                                                 break;
1790                                 }
1791                                 if (i >= SHADERPERMUTATION_COUNT)
1792                                 {
1793                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1794                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1795                                         return; // no bit left to clear, entire mode is broken
1796                                 }
1797                         }
1798                 }
1799                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1800                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1801         }
1802         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1803         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1804         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1805 }
1806 #endif
1807
1808 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1809 {
1810         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1811         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1812         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1813         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1814 }
1815
1816 void R_GLSL_Restart_f(void)
1817 {
1818         unsigned int i, limit;
1819         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1820                 Mem_Free(glslshaderstring);
1821         glslshaderstring = NULL;
1822         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1823                 Mem_Free(hlslshaderstring);
1824         hlslshaderstring = NULL;
1825         switch(vid.renderpath)
1826         {
1827         case RENDERPATH_D3D9:
1828 #ifdef SUPPORTD3D
1829                 {
1830                         r_hlsl_permutation_t *p;
1831                         r_hlsl_permutation = NULL;
1832                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1833                         for (i = 0;i < limit;i++)
1834                         {
1835                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1836                                 {
1837                                         if (p->vertexshader)
1838                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1839                                         if (p->pixelshader)
1840                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1841                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1842                                 }
1843                         }
1844                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1845                 }
1846 #endif
1847                 break;
1848         case RENDERPATH_D3D10:
1849                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1850                 break;
1851         case RENDERPATH_D3D11:
1852                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1853                 break;
1854         case RENDERPATH_GL20:
1855         case RENDERPATH_GLES2:
1856                 {
1857                         r_glsl_permutation_t *p;
1858                         r_glsl_permutation = NULL;
1859                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1860                         for (i = 0;i < limit;i++)
1861                         {
1862                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1863                                 {
1864                                         GL_Backend_FreeProgram(p->program);
1865                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1866                                 }
1867                         }
1868                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1869                 }
1870                 break;
1871         case RENDERPATH_GL11:
1872         case RENDERPATH_GL13:
1873         case RENDERPATH_GLES1:
1874                 break;
1875         case RENDERPATH_SOFT:
1876                 break;
1877         }
1878 }
1879
1880 static void R_GLSL_DumpShader_f(void)
1881 {
1882         int i;
1883         qfile_t *file;
1884
1885         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1886         if (file)
1887         {
1888                 FS_Print(file, "/* The engine may define the following macros:\n");
1889                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1890                 for (i = 0;i < SHADERMODE_COUNT;i++)
1891                         FS_Print(file, glslshadermodeinfo[i].pretext);
1892                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1893                         FS_Print(file, shaderpermutationinfo[i].pretext);
1894                 FS_Print(file, "*/\n");
1895                 FS_Print(file, builtinshaderstring);
1896                 FS_Close(file);
1897                 Con_Printf("glsl/default.glsl written\n");
1898         }
1899         else
1900                 Con_Printf("failed to write to glsl/default.glsl\n");
1901
1902         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1903         if (file)
1904         {
1905                 FS_Print(file, "/* The engine may define the following macros:\n");
1906                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1907                 for (i = 0;i < SHADERMODE_COUNT;i++)
1908                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1909                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1910                         FS_Print(file, shaderpermutationinfo[i].pretext);
1911                 FS_Print(file, "*/\n");
1912                 FS_Print(file, builtinhlslshaderstring);
1913                 FS_Close(file);
1914                 Con_Printf("hlsl/default.hlsl written\n");
1915         }
1916         else
1917                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1918 }
1919
1920 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1921 {
1922         unsigned int permutation = 0;
1923         if (r_trippy.integer && !notrippy)
1924                 permutation |= SHADERPERMUTATION_TRIPPY;
1925         permutation |= SHADERPERMUTATION_VIEWTINT;
1926         if (first)
1927                 permutation |= SHADERPERMUTATION_DIFFUSE;
1928         if (second)
1929                 permutation |= SHADERPERMUTATION_SPECULAR;
1930         if (texturemode == GL_MODULATE)
1931                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1932         else if (texturemode == GL_ADD)
1933                 permutation |= SHADERPERMUTATION_GLOW;
1934         else if (texturemode == GL_DECAL)
1935                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1936         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1937                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1938         if (suppresstexalpha)
1939                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1940         if (!second)
1941                 texturemode = GL_MODULATE;
1942         if (vid.allowalphatocoverage)
1943                 GL_AlphaToCoverage(false);
1944         switch (vid.renderpath)
1945         {
1946         case RENDERPATH_D3D9:
1947 #ifdef SUPPORTD3D
1948                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1949                 R_Mesh_TexBind(GL20TU_FIRST , first );
1950                 R_Mesh_TexBind(GL20TU_SECOND, second);
1951                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1952                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1953 #endif
1954                 break;
1955         case RENDERPATH_D3D10:
1956                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1957                 break;
1958         case RENDERPATH_D3D11:
1959                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1960                 break;
1961         case RENDERPATH_GL20:
1962         case RENDERPATH_GLES2:
1963                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1964                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1965                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1966                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1967                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1968                 break;
1969         case RENDERPATH_GL13:
1970         case RENDERPATH_GLES1:
1971                 R_Mesh_TexBind(0, first );
1972                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1973                 R_Mesh_TexBind(1, second);
1974                 if (second)
1975                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1976                 break;
1977         case RENDERPATH_GL11:
1978                 R_Mesh_TexBind(0, first );
1979                 break;
1980         case RENDERPATH_SOFT:
1981                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1982                 R_Mesh_TexBind(GL20TU_FIRST , first );
1983                 R_Mesh_TexBind(GL20TU_SECOND, second);
1984                 break;
1985         }
1986 }
1987
1988 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1989 {
1990         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1991 }
1992
1993 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1994 {
1995         unsigned int permutation = 0;
1996         if (r_trippy.integer && !notrippy)
1997                 permutation |= SHADERPERMUTATION_TRIPPY;
1998         if (depthrgb)
1999                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2000         if (vid.allowalphatocoverage)
2001                 GL_AlphaToCoverage(false);
2002         switch (vid.renderpath)
2003         {
2004         case RENDERPATH_D3D9:
2005 #ifdef SUPPORTD3D
2006                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2007 #endif
2008                 break;
2009         case RENDERPATH_D3D10:
2010                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2011                 break;
2012         case RENDERPATH_D3D11:
2013                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2014                 break;
2015         case RENDERPATH_GL20:
2016         case RENDERPATH_GLES2:
2017                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2018                 break;
2019         case RENDERPATH_GL13:
2020         case RENDERPATH_GLES1:
2021                 R_Mesh_TexBind(0, 0);
2022                 R_Mesh_TexBind(1, 0);
2023                 break;
2024         case RENDERPATH_GL11:
2025                 R_Mesh_TexBind(0, 0);
2026                 break;
2027         case RENDERPATH_SOFT:
2028                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2029                 break;
2030         }
2031 }
2032
2033 void R_SetupShader_ShowDepth(qboolean notrippy)
2034 {
2035         int permutation = 0;
2036         if (r_trippy.integer && !notrippy)
2037                 permutation |= SHADERPERMUTATION_TRIPPY;
2038         if (vid.allowalphatocoverage)
2039                 GL_AlphaToCoverage(false);
2040         switch (vid.renderpath)
2041         {
2042         case RENDERPATH_D3D9:
2043 #ifdef SUPPORTHLSL
2044                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2045 #endif
2046                 break;
2047         case RENDERPATH_D3D10:
2048                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2049                 break;
2050         case RENDERPATH_D3D11:
2051                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2052                 break;
2053         case RENDERPATH_GL20:
2054         case RENDERPATH_GLES2:
2055                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2056                 break;
2057         case RENDERPATH_GL13:
2058         case RENDERPATH_GLES1:
2059                 break;
2060         case RENDERPATH_GL11:
2061                 break;
2062         case RENDERPATH_SOFT:
2063                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2064                 break;
2065         }
2066 }
2067
2068 extern qboolean r_shadow_usingdeferredprepass;
2069 extern rtexture_t *r_shadow_attenuationgradienttexture;
2070 extern rtexture_t *r_shadow_attenuation2dtexture;
2071 extern rtexture_t *r_shadow_attenuation3dtexture;
2072 extern qboolean r_shadow_usingshadowmap2d;
2073 extern qboolean r_shadow_usingshadowmaportho;
2074 extern float r_shadow_shadowmap_texturescale[2];
2075 extern float r_shadow_shadowmap_parameters[4];
2076 extern qboolean r_shadow_shadowmapvsdct;
2077 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2078 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2079 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2080 extern matrix4x4_t r_shadow_shadowmapmatrix;
2081 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2082 extern int r_shadow_prepass_width;
2083 extern int r_shadow_prepass_height;
2084 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2085 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2086 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2087 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2088
2089 #define BLENDFUNC_ALLOWS_COLORMOD      1
2090 #define BLENDFUNC_ALLOWS_FOG           2
2091 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2092 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2093 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2094 static int R_BlendFuncFlags(int src, int dst)
2095 {
2096         int r = 0;
2097
2098         // a blendfunc allows colormod if:
2099         // a) it can never keep the destination pixel invariant, or
2100         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2101         // this is to prevent unintended side effects from colormod
2102
2103         // a blendfunc allows fog if:
2104         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2105         // this is to prevent unintended side effects from fog
2106
2107         // these checks are the output of fogeval.pl
2108
2109         r |= BLENDFUNC_ALLOWS_COLORMOD;
2110         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2111         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2112         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2113         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2114         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2115         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2116         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2117         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2118         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2119         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2120         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2121         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2122         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2123         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2124         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2125         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2126         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2127         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2128         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2129         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2130         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2131
2132         return r;
2133 }
2134
2135 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)
2136 {
2137         // select a permutation of the lighting shader appropriate to this
2138         // combination of texture, entity, light source, and fogging, only use the
2139         // minimum features necessary to avoid wasting rendering time in the
2140         // fragment shader on features that are not being used
2141         unsigned int permutation = 0;
2142         unsigned int mode = 0;
2143         int blendfuncflags;
2144         static float dummy_colormod[3] = {1, 1, 1};
2145         float *colormod = rsurface.colormod;
2146         float m16f[16];
2147         matrix4x4_t tempmatrix;
2148         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2149         if (r_trippy.integer && !notrippy)
2150                 permutation |= SHADERPERMUTATION_TRIPPY;
2151         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2152                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2153         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2154                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2155         if (rsurfacepass == RSURFPASS_BACKGROUND)
2156         {
2157                 // distorted background
2158                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2159                 {
2160                         mode = SHADERMODE_WATER;
2161                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2162                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2163                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2164                         {
2165                                 // this is the right thing to do for wateralpha
2166                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2167                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2168                         }
2169                         else
2170                         {
2171                                 // this is the right thing to do for entity alpha
2172                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2173                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2174                         }
2175                 }
2176                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2177                 {
2178                         mode = SHADERMODE_REFRACTION;
2179                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2180                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2181                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2182                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2183                 }
2184                 else
2185                 {
2186                         mode = SHADERMODE_GENERIC;
2187                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2188                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2189                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2190                 }
2191                 if (vid.allowalphatocoverage)
2192                         GL_AlphaToCoverage(false);
2193         }
2194         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2195         {
2196                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2197                 {
2198                         switch(rsurface.texture->offsetmapping)
2199                         {
2200                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2201                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2203                         case OFFSETMAPPING_OFF: break;
2204                         }
2205                 }
2206                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2207                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2208                 // normalmap (deferred prepass), may use alpha test on diffuse
2209                 mode = SHADERMODE_DEFERREDGEOMETRY;
2210                 GL_BlendFunc(GL_ONE, GL_ZERO);
2211                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2212                 if (vid.allowalphatocoverage)
2213                         GL_AlphaToCoverage(false);
2214         }
2215         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2216         {
2217                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2218                 {
2219                         switch(rsurface.texture->offsetmapping)
2220                         {
2221                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2222                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2223                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2224                         case OFFSETMAPPING_OFF: break;
2225                         }
2226                 }
2227                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2228                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2229                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2230                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2231                 // light source
2232                 mode = SHADERMODE_LIGHTSOURCE;
2233                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2234                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2235                 if (diffusescale > 0)
2236                         permutation |= SHADERPERMUTATION_DIFFUSE;
2237                 if (specularscale > 0)
2238                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2239                 if (r_refdef.fogenabled)
2240                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2241                 if (rsurface.texture->colormapping)
2242                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2243                 if (r_shadow_usingshadowmap2d)
2244                 {
2245                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2246                         if(r_shadow_shadowmapvsdct)
2247                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2248
2249                         if (r_shadow_shadowmap2ddepthbuffer)
2250                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2251                 }
2252                 if (rsurface.texture->reflectmasktexture)
2253                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2254                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2255                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2256                 if (vid.allowalphatocoverage)
2257                         GL_AlphaToCoverage(false);
2258         }
2259         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2260         {
2261                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2262                 {
2263                         switch(rsurface.texture->offsetmapping)
2264                         {
2265                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2266                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2267                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2268                         case OFFSETMAPPING_OFF: break;
2269                         }
2270                 }
2271                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2272                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2273                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2274                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2275                 // unshaded geometry (fullbright or ambient model lighting)
2276                 mode = SHADERMODE_FLATCOLOR;
2277                 ambientscale = diffusescale = specularscale = 0;
2278                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2279                         permutation |= SHADERPERMUTATION_GLOW;
2280                 if (r_refdef.fogenabled)
2281                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2282                 if (rsurface.texture->colormapping)
2283                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2284                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2285                 {
2286                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2287                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2288
2289                         if (r_shadow_shadowmap2ddepthbuffer)
2290                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2291                 }
2292                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2293                         permutation |= SHADERPERMUTATION_REFLECTION;
2294                 if (rsurface.texture->reflectmasktexture)
2295                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2296                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2297                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2298                 // when using alphatocoverage, we don't need alphakill
2299                 if (vid.allowalphatocoverage)
2300                 {
2301                         if (r_transparent_alphatocoverage.integer)
2302                         {
2303                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2304                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2305                         }
2306                         else
2307                                 GL_AlphaToCoverage(false);
2308                 }
2309         }
2310         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2311         {
2312                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2313                 {
2314                         switch(rsurface.texture->offsetmapping)
2315                         {
2316                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2317                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2318                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2319                         case OFFSETMAPPING_OFF: break;
2320                         }
2321                 }
2322                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2323                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2324                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2325                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2326                 // directional model lighting
2327                 mode = SHADERMODE_LIGHTDIRECTION;
2328                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2329                         permutation |= SHADERPERMUTATION_GLOW;
2330                 permutation |= SHADERPERMUTATION_DIFFUSE;
2331                 if (specularscale > 0)
2332                         permutation |= SHADERPERMUTATION_SPECULAR;
2333                 if (r_refdef.fogenabled)
2334                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2335                 if (rsurface.texture->colormapping)
2336                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2337                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2338                 {
2339                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2340                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2341
2342                         if (r_shadow_shadowmap2ddepthbuffer)
2343                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2344                 }
2345                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2346                         permutation |= SHADERPERMUTATION_REFLECTION;
2347                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2348                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2349                 if (rsurface.texture->reflectmasktexture)
2350                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2351                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2352                 {
2353                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2354                         if (r_shadow_bouncegriddirectional)
2355                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2356                 }
2357                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2358                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2359                 // when using alphatocoverage, we don't need alphakill
2360                 if (vid.allowalphatocoverage)
2361                 {
2362                         if (r_transparent_alphatocoverage.integer)
2363                         {
2364                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2365                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2366                         }
2367                         else
2368                                 GL_AlphaToCoverage(false);
2369                 }
2370         }
2371         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2372         {
2373                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2374                 {
2375                         switch(rsurface.texture->offsetmapping)
2376                         {
2377                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2378                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2379                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2380                         case OFFSETMAPPING_OFF: break;
2381                         }
2382                 }
2383                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2384                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2385                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2386                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2387                 // ambient model lighting
2388                 mode = SHADERMODE_LIGHTDIRECTION;
2389                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2390                         permutation |= SHADERPERMUTATION_GLOW;
2391                 if (r_refdef.fogenabled)
2392                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2393                 if (rsurface.texture->colormapping)
2394                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2395                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2396                 {
2397                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2398                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2399
2400                         if (r_shadow_shadowmap2ddepthbuffer)
2401                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2402                 }
2403                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2404                         permutation |= SHADERPERMUTATION_REFLECTION;
2405                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2406                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2407                 if (rsurface.texture->reflectmasktexture)
2408                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2409                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2410                 {
2411                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2412                         if (r_shadow_bouncegriddirectional)
2413                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2414                 }
2415                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2416                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2417                 // when using alphatocoverage, we don't need alphakill
2418                 if (vid.allowalphatocoverage)
2419                 {
2420                         if (r_transparent_alphatocoverage.integer)
2421                         {
2422                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2423                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2424                         }
2425                         else
2426                                 GL_AlphaToCoverage(false);
2427                 }
2428         }
2429         else
2430         {
2431                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2432                 {
2433                         switch(rsurface.texture->offsetmapping)
2434                         {
2435                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2436                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2437                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2438                         case OFFSETMAPPING_OFF: break;
2439                         }
2440                 }
2441                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2442                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2443                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2444                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2445                 // lightmapped wall
2446                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2447                         permutation |= SHADERPERMUTATION_GLOW;
2448                 if (r_refdef.fogenabled)
2449                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2450                 if (rsurface.texture->colormapping)
2451                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2452                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2453                 {
2454                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2455                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2456
2457                         if (r_shadow_shadowmap2ddepthbuffer)
2458                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2459                 }
2460                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2461                         permutation |= SHADERPERMUTATION_REFLECTION;
2462                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2463                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2464                 if (rsurface.texture->reflectmasktexture)
2465                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2466                 if (FAKELIGHT_ENABLED)
2467                 {
2468                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2469                         mode = SHADERMODE_FAKELIGHT;
2470                         permutation |= SHADERPERMUTATION_DIFFUSE;
2471                         if (specularscale > 0)
2472                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2473                 }
2474                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2475                 {
2476                         // deluxemapping (light direction texture)
2477                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2478                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2479                         else
2480                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2481                         permutation |= SHADERPERMUTATION_DIFFUSE;
2482                         if (specularscale > 0)
2483                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2484                 }
2485                 else if (r_glsl_deluxemapping.integer >= 2)
2486                 {
2487                         // fake deluxemapping (uniform light direction in tangentspace)
2488                         if (rsurface.uselightmaptexture)
2489                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2490                         else
2491                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2492                         permutation |= SHADERPERMUTATION_DIFFUSE;
2493                         if (specularscale > 0)
2494                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2495                 }
2496                 else if (rsurface.uselightmaptexture)
2497                 {
2498                         // ordinary lightmapping (q1bsp, q3bsp)
2499                         mode = SHADERMODE_LIGHTMAP;
2500                 }
2501                 else
2502                 {
2503                         // ordinary vertex coloring (q3bsp)
2504                         mode = SHADERMODE_VERTEXCOLOR;
2505                 }
2506                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2507                 {
2508                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2509                         if (r_shadow_bouncegriddirectional)
2510                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2511                 }
2512                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2513                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2514                 // when using alphatocoverage, we don't need alphakill
2515                 if (vid.allowalphatocoverage)
2516                 {
2517                         if (r_transparent_alphatocoverage.integer)
2518                         {
2519                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2520                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2521                         }
2522                         else
2523                                 GL_AlphaToCoverage(false);
2524                 }
2525         }
2526         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2527                 colormod = dummy_colormod;
2528         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2529                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2530         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2531                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2532         switch(vid.renderpath)
2533         {
2534         case RENDERPATH_D3D9:
2535 #ifdef SUPPORTD3D
2536                 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), texturenumsurfaces, texturesurfacelist);
2537                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2538                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2539                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2540                 if (mode == SHADERMODE_LIGHTSOURCE)
2541                 {
2542                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2543                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2544                 }
2545                 else
2546                 {
2547                         if (mode == SHADERMODE_LIGHTDIRECTION)
2548                         {
2549                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2550                         }
2551                 }
2552                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2553                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2554                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2555                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2556                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2557
2558                 if (mode == SHADERMODE_LIGHTSOURCE)
2559                 {
2560                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2561                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2562                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2563                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2564                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2565
2566                         // additive passes are only darkened by fog, not tinted
2567                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2568                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2569                 }
2570                 else
2571                 {
2572                         if (mode == SHADERMODE_FLATCOLOR)
2573                         {
2574                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2575                         }
2576                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2577                         {
2578                                 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]);
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2580                                 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);
2581                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2582                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2583                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2584                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2585                         }
2586                         else
2587                         {
2588                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2589                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2590                                 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);
2591                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2592                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2593                         }
2594                         // additive passes are only darkened by fog, not tinted
2595                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2596                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2597                         else
2598                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2599                         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);
2600                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2601                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2602                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2603                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2604                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2605                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2606                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2607                         if (mode == SHADERMODE_WATER)
2608                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2609                 }
2610                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2611                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2612                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2613                 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));
2614                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2615                 if (rsurface.texture->pantstexture)
2616                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2617                 else
2618                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2619                 if (rsurface.texture->shirttexture)
2620                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2621                 else
2622                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2623                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2624                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2625                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2626                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2627                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2628                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2629                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2630                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2631                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2632                         );
2633                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2634                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2635                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2636                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2637
2638                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2639                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2640                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2641                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2642                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2643                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2644                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2645                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2646                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2647                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2648                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2649                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2650                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2651                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2652                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2653                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2654                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2655                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2656                 {
2657                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2658                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2659                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2660                 }
2661                 else
2662                 {
2663                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2664                 }
2665 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2666                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2667                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2668                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2669                 {
2670                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2671                         if (rsurface.rtlight)
2672                         {
2673                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2674                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2675                         }
2676                 }
2677 #endif
2678                 break;
2679         case RENDERPATH_D3D10:
2680                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2681                 break;
2682         case RENDERPATH_D3D11:
2683                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2684                 break;
2685         case RENDERPATH_GL20:
2686         case RENDERPATH_GLES2:
2687                 if (!vid.useinterleavedarrays)
2688                 {
2689                         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), texturenumsurfaces, texturesurfacelist);
2690                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2691                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2692                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2693                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2694                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2695                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2696                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2697                 }
2698                 else
2699                 {
2700                         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), texturenumsurfaces, texturesurfacelist);
2701                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2702                 }
2703                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2704                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2705                 if (mode == SHADERMODE_LIGHTSOURCE)
2706                 {
2707                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2708                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2709                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2710                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2711                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2712                         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);
2713         
2714                         // additive passes are only darkened by fog, not tinted
2715                         if (r_glsl_permutation->loc_FogColor >= 0)
2716                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2717                         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);
2718                 }
2719                 else
2720                 {
2721                         if (mode == SHADERMODE_FLATCOLOR)
2722                         {
2723                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2724                         }
2725                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2726                         {
2727                                 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]);
2728                                 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]);
2729                                 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);
2730                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2731                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2732                                 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]);
2733                                 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]);
2734                         }
2735                         else
2736                         {
2737                                 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]);
2738                                 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]);
2739                                 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);
2740                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2741                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2742                         }
2743                         // additive passes are only darkened by fog, not tinted
2744                         if (r_glsl_permutation->loc_FogColor >= 0)
2745                         {
2746                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2747                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2748                                 else
2749                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2750                         }
2751                         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);
2752                         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]);
2753                         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]);
2754                         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]);
2755                         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]);
2756                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2757                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2758                         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);
2759                         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]);
2760                 }
2761                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2762                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2763                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2764                 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]);
2765                 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]);
2766
2767                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2768                 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));
2769                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2770                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2771                 {
2772                         if (rsurface.texture->pantstexture)
2773                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2774                         else
2775                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2776                 }
2777                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2778                 {
2779                         if (rsurface.texture->shirttexture)
2780                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2781                         else
2782                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2783                 }
2784                 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]);
2785                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2786                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2787                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2788                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2789                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2790                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2791                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2792                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2793                         );
2794                 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);
2795                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2796                 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]);
2797                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2798                 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);}
2799                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2800
2801                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2802                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2803                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2804                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2805                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2806                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2807                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2808                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2809                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2810                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2811                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2812                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2813                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2814                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2815                 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);
2816                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2817                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2818                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2819                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2820                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2821                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2822                 {
2823                         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);
2824                         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);
2825                         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);
2826                 }
2827                 else
2828                 {
2829                         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);
2830                 }
2831                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2832                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2833                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2834                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2835                 {
2836                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2837                         if (rsurface.rtlight)
2838                         {
2839                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2840                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2841                         }
2842                 }
2843                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2844                 CHECKGLERROR
2845                 break;
2846         case RENDERPATH_GL11:
2847         case RENDERPATH_GL13:
2848         case RENDERPATH_GLES1:
2849                 break;
2850         case RENDERPATH_SOFT:
2851                 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), texturenumsurfaces, texturesurfacelist);
2852                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2853                 R_SetupShader_SetPermutationSoft(mode, permutation);
2854                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2855                 if (mode == SHADERMODE_LIGHTSOURCE)
2856                 {
2857                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2858                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2859                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2860                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2861                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2862                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2863         
2864                         // additive passes are only darkened by fog, not tinted
2865                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2866                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2867                 }
2868                 else
2869                 {
2870                         if (mode == SHADERMODE_FLATCOLOR)
2871                         {
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2873                         }
2874                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2875                         {
2876                                 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]);
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2878                                 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);
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2881                                 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]);
2882                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2883                         }
2884                         else
2885                         {
2886                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2888                                 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);
2889                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2890                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2891                         }
2892                         // additive passes are only darkened by fog, not tinted
2893                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2895                         else
2896                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2897                         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);
2898                         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]);
2899                         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]);
2900                         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]);
2901                         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]);
2902                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2903                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2904                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2905                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2906                 }
2907                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2908                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2909                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2910                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2911                 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]);
2912
2913                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2914                 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));
2915                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2916                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2917                 {
2918                         if (rsurface.texture->pantstexture)
2919                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2920                         else
2921                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2922                 }
2923                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2924                 {
2925                         if (rsurface.texture->shirttexture)
2926                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2927                         else
2928                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2929                 }
2930                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2931                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2932                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2933                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2934                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2935                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2936                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2937                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2938                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2939                         );
2940                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2941                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2942                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2943                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2944
2945                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2946                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2947                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2948                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2949                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2950                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2951                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2952                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2953                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2954                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2955                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2956                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2957                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2958                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2959                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2960                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2961                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2962                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2963                 {
2964                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2965                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2966                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2967                 }
2968                 else
2969                 {
2970                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2971                 }
2972 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2973                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2974                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2975                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2976                 {
2977                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2978                         if (rsurface.rtlight)
2979                         {
2980                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2981                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2982                         }
2983                 }
2984                 break;
2985         }
2986 }
2987
2988 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2989 {
2990         // select a permutation of the lighting shader appropriate to this
2991         // combination of texture, entity, light source, and fogging, only use the
2992         // minimum features necessary to avoid wasting rendering time in the
2993         // fragment shader on features that are not being used
2994         unsigned int permutation = 0;
2995         unsigned int mode = 0;
2996         const float *lightcolorbase = rtlight->currentcolor;
2997         float ambientscale = rtlight->ambientscale;
2998         float diffusescale = rtlight->diffusescale;
2999         float specularscale = rtlight->specularscale;
3000         // this is the location of the light in view space
3001         vec3_t viewlightorigin;
3002         // this transforms from view space (camera) to light space (cubemap)
3003         matrix4x4_t viewtolight;
3004         matrix4x4_t lighttoview;
3005         float viewtolight16f[16];
3006         // light source
3007         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3008         if (rtlight->currentcubemap != r_texture_whitecube)
3009                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3010         if (diffusescale > 0)
3011                 permutation |= SHADERPERMUTATION_DIFFUSE;
3012         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3013                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3014         if (r_shadow_usingshadowmap2d)
3015         {
3016                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3017                 if (r_shadow_shadowmapvsdct)
3018                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3019
3020                 if (r_shadow_shadowmap2ddepthbuffer)
3021                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3022         }
3023         if (vid.allowalphatocoverage)
3024                 GL_AlphaToCoverage(false);
3025         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3026         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3027         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3028         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3029         switch(vid.renderpath)
3030         {
3031         case RENDERPATH_D3D9:
3032 #ifdef SUPPORTD3D
3033                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3034                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3035                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3036                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3037                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3038                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3039                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3040                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3041                 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);
3042                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3043                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3044
3045                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3046                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3047                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3048                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3049                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3050 #endif
3051                 break;
3052         case RENDERPATH_D3D10:
3053                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3054                 break;
3055         case RENDERPATH_D3D11:
3056                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3057                 break;
3058         case RENDERPATH_GL20:
3059         case RENDERPATH_GLES2:
3060                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3061                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3062                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3063                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3064                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3065                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3066                 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]);
3067                 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]);
3068                 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);
3069                 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]);
3070                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3071
3072                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3073                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3074                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3075                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3076                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3077                 break;
3078         case RENDERPATH_GL11:
3079         case RENDERPATH_GL13:
3080         case RENDERPATH_GLES1:
3081                 break;
3082         case RENDERPATH_SOFT:
3083                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3084                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3085                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3086                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3087                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3088                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3089                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3090                 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]);
3091                 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);
3092                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3093                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3094
3095                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3096                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3097                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3098                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3099                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3100                 break;
3101         }
3102 }
3103
3104 #define SKINFRAME_HASH 1024
3105
3106 typedef struct
3107 {
3108         int loadsequence; // incremented each level change
3109         memexpandablearray_t array;
3110         skinframe_t *hash[SKINFRAME_HASH];
3111 }
3112 r_skinframe_t;
3113 r_skinframe_t r_skinframe;
3114
3115 void R_SkinFrame_PrepareForPurge(void)
3116 {
3117         r_skinframe.loadsequence++;
3118         // wrap it without hitting zero
3119         if (r_skinframe.loadsequence >= 200)
3120                 r_skinframe.loadsequence = 1;
3121 }
3122
3123 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3124 {
3125         if (!skinframe)
3126                 return;
3127         // mark the skinframe as used for the purging code
3128         skinframe->loadsequence = r_skinframe.loadsequence;
3129 }
3130
3131 void R_SkinFrame_Purge(void)
3132 {
3133         int i;
3134         skinframe_t *s;
3135         for (i = 0;i < SKINFRAME_HASH;i++)
3136         {
3137                 for (s = r_skinframe.hash[i];s;s = s->next)
3138                 {
3139                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3140                         {
3141                                 if (s->merged == s->base)
3142                                         s->merged = NULL;
3143                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3144                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3145                                 R_PurgeTexture(s->merged);s->merged = NULL;
3146                                 R_PurgeTexture(s->base  );s->base   = NULL;
3147                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3148                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3149                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3150                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3151                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3152                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3153                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3154                                 s->loadsequence = 0;
3155                         }
3156                 }
3157         }
3158 }
3159
3160 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3161         skinframe_t *item;
3162         char basename[MAX_QPATH];
3163
3164         Image_StripImageExtension(name, basename, sizeof(basename));
3165
3166         if( last == NULL ) {
3167                 int hashindex;
3168                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3169                 item = r_skinframe.hash[hashindex];
3170         } else {
3171                 item = last->next;
3172         }
3173
3174         // linearly search through the hash bucket
3175         for( ; item ; item = item->next ) {
3176                 if( !strcmp( item->basename, basename ) ) {
3177                         return item;
3178                 }
3179         }
3180         return NULL;
3181 }
3182
3183 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3184 {
3185         skinframe_t *item;
3186         int hashindex;
3187         char basename[MAX_QPATH];
3188
3189         Image_StripImageExtension(name, basename, sizeof(basename));
3190
3191         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3192         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3193                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3194                         break;
3195
3196         if (!item) {
3197                 rtexture_t *dyntexture;
3198                 // check whether its a dynamic texture
3199                 dyntexture = CL_GetDynTexture( basename );
3200                 if (!add && !dyntexture)
3201                         return NULL;
3202                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3203                 memset(item, 0, sizeof(*item));
3204                 strlcpy(item->basename, basename, sizeof(item->basename));
3205                 item->base = dyntexture; // either NULL or dyntexture handle
3206                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3207                 item->comparewidth = comparewidth;
3208                 item->compareheight = compareheight;
3209                 item->comparecrc = comparecrc;
3210                 item->next = r_skinframe.hash[hashindex];
3211                 r_skinframe.hash[hashindex] = item;
3212         }
3213         else if (textureflags & TEXF_FORCE_RELOAD)
3214         {
3215                 rtexture_t *dyntexture;
3216                 // check whether its a dynamic texture
3217                 dyntexture = CL_GetDynTexture( basename );
3218                 if (!add && !dyntexture)
3219                         return NULL;
3220                 if (item->merged == item->base)
3221                         item->merged = NULL;
3222                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3223                 R_PurgeTexture(item->stain );item->stain  = NULL;
3224                 R_PurgeTexture(item->merged);item->merged = NULL;
3225                 R_PurgeTexture(item->base  );item->base   = NULL;
3226                 R_PurgeTexture(item->pants );item->pants  = NULL;
3227                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3228                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3229                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3230                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3231                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3232         R_PurgeTexture(item->reflect);item->reflect = NULL;
3233                 item->loadsequence = 0;
3234         }
3235         else if( item->base == NULL )
3236         {
3237                 rtexture_t *dyntexture;
3238                 // check whether its a dynamic texture
3239                 // 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]
3240                 dyntexture = CL_GetDynTexture( basename );
3241                 item->base = dyntexture; // either NULL or dyntexture handle
3242         }
3243
3244         R_SkinFrame_MarkUsed(item);
3245         return item;
3246 }
3247
3248 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3249         { \
3250                 unsigned long long avgcolor[5], wsum; \
3251                 int pix, comp, w; \
3252                 avgcolor[0] = 0; \
3253                 avgcolor[1] = 0; \
3254                 avgcolor[2] = 0; \
3255                 avgcolor[3] = 0; \
3256                 avgcolor[4] = 0; \
3257                 wsum = 0; \
3258                 for(pix = 0; pix < cnt; ++pix) \
3259                 { \
3260                         w = 0; \
3261                         for(comp = 0; comp < 3; ++comp) \
3262                                 w += getpixel; \
3263                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3264                         { \
3265                                 ++wsum; \
3266                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3267                                 w = getpixel; \
3268                                 for(comp = 0; comp < 3; ++comp) \
3269                                         avgcolor[comp] += getpixel * w; \
3270                                 avgcolor[3] += w; \
3271                         } \
3272                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3273                         avgcolor[4] += getpixel; \
3274                 } \
3275                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3276                         avgcolor[3] = 1; \
3277                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3278                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3279                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3280                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3281         }
3282
3283 extern cvar_t gl_picmip;
3284 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3285 {
3286         int j;
3287         unsigned char *pixels;
3288         unsigned char *bumppixels;
3289         unsigned char *basepixels = NULL;
3290         int basepixels_width = 0;
3291         int basepixels_height = 0;
3292         skinframe_t *skinframe;
3293         rtexture_t *ddsbase = NULL;
3294         qboolean ddshasalpha = false;
3295         float ddsavgcolor[4];
3296         char basename[MAX_QPATH];
3297         int miplevel = R_PicmipForFlags(textureflags);
3298         int savemiplevel = miplevel;
3299         int mymiplevel;
3300         char vabuf[1024];
3301
3302         if (cls.state == ca_dedicated)
3303                 return NULL;
3304
3305         // return an existing skinframe if already loaded
3306         // if loading of the first image fails, don't make a new skinframe as it
3307         // would cause all future lookups of this to be missing
3308         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3309         if (skinframe && skinframe->base)
3310                 return skinframe;
3311
3312         Image_StripImageExtension(name, basename, sizeof(basename));
3313
3314         // check for DDS texture file first
3315         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3316         {
3317                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3318                 if (basepixels == NULL)
3319                         return NULL;
3320         }
3321
3322         // FIXME handle miplevel
3323
3324         if (developer_loading.integer)
3325                 Con_Printf("loading skin \"%s\"\n", name);
3326
3327         // we've got some pixels to store, so really allocate this new texture now
3328         if (!skinframe)
3329                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3330         textureflags &= ~TEXF_FORCE_RELOAD;
3331         skinframe->stain = NULL;
3332         skinframe->merged = NULL;
3333         skinframe->base = NULL;
3334         skinframe->pants = NULL;
3335         skinframe->shirt = NULL;
3336         skinframe->nmap = NULL;
3337         skinframe->gloss = NULL;
3338         skinframe->glow = NULL;
3339         skinframe->fog = NULL;
3340         skinframe->reflect = NULL;
3341         skinframe->hasalpha = false;
3342
3343         if (ddsbase)
3344         {
3345                 skinframe->base = ddsbase;
3346                 skinframe->hasalpha = ddshasalpha;
3347                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3348                 if (r_loadfog && skinframe->hasalpha)
3349                         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);
3350                 //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]);
3351         }
3352         else
3353         {
3354                 basepixels_width = image_width;
3355                 basepixels_height = image_height;
3356                 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);
3357                 if (textureflags & TEXF_ALPHA)
3358                 {
3359                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3360                         {
3361                                 if (basepixels[j] < 255)
3362                                 {
3363                                         skinframe->hasalpha = true;
3364                                         break;
3365                                 }
3366                         }
3367                         if (r_loadfog && skinframe->hasalpha)
3368                         {
3369                                 // has transparent pixels
3370                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3371                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3372                                 {
3373                                         pixels[j+0] = 255;
3374                                         pixels[j+1] = 255;
3375                                         pixels[j+2] = 255;
3376                                         pixels[j+3] = basepixels[j+3];
3377                                 }
3378                                 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);
3379                                 Mem_Free(pixels);
3380                         }
3381                 }
3382                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3383 #ifndef USE_GLES2
3384                 //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]);
3385                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3386                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3387                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3388                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3389 #endif
3390         }
3391
3392         if (r_loaddds)
3393         {
3394                 mymiplevel = savemiplevel;
3395                 if (r_loadnormalmap)
3396                         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);
3397                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3398                 if (r_loadgloss)
3399                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3400                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3401                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3402                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3403         }
3404
3405         // _norm is the name used by tenebrae and has been adopted as standard
3406         if (r_loadnormalmap && skinframe->nmap == NULL)
3407         {
3408                 mymiplevel = savemiplevel;
3409                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3410                 {
3411                         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);
3412                         Mem_Free(pixels);
3413                         pixels = NULL;
3414                 }
3415                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3416                 {
3417                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3418                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3419                         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);
3420                         Mem_Free(pixels);
3421                         Mem_Free(bumppixels);
3422                 }
3423                 else if (r_shadow_bumpscale_basetexture.value > 0)
3424                 {
3425                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3426                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3427                         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);
3428                         Mem_Free(pixels);
3429                 }
3430 #ifndef USE_GLES2
3431                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3432                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3433 #endif
3434         }
3435
3436         // _luma is supported only for tenebrae compatibility
3437         // _glow is the preferred name
3438         mymiplevel = savemiplevel;
3439         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))))
3440         {
3441                 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);
3442 #ifndef USE_GLES2
3443                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3444                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3445 #endif
3446                 Mem_Free(pixels);pixels = NULL;
3447         }
3448
3449         mymiplevel = savemiplevel;
3450         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3451         {
3452                 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);
3453 #ifndef USE_GLES2
3454                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3455                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3456 #endif
3457                 Mem_Free(pixels);
3458                 pixels = NULL;
3459         }
3460
3461         mymiplevel = savemiplevel;
3462         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3463         {
3464                 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);
3465 #ifndef USE_GLES2
3466                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3467                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3468 #endif
3469                 Mem_Free(pixels);
3470                 pixels = NULL;
3471         }
3472
3473         mymiplevel = savemiplevel;
3474         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3475         {
3476                 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);
3477 #ifndef USE_GLES2
3478                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3479                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3480 #endif
3481                 Mem_Free(pixels);
3482                 pixels = NULL;
3483         }
3484
3485         mymiplevel = savemiplevel;
3486         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3487         {
3488                 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);
3489 #ifndef USE_GLES2
3490                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3491                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3492 #endif
3493                 Mem_Free(pixels);
3494                 pixels = NULL;
3495         }
3496
3497         if (basepixels)
3498                 Mem_Free(basepixels);
3499
3500         return skinframe;
3501 }
3502
3503 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3504 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3505 {
3506         int i;
3507         unsigned char *temp1, *temp2;
3508         skinframe_t *skinframe;
3509         char vabuf[1024];
3510
3511         if (cls.state == ca_dedicated)
3512                 return NULL;
3513
3514         // if already loaded just return it, otherwise make a new skinframe
3515         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3516         if (skinframe->base)
3517                 return skinframe;
3518         textureflags &= ~TEXF_FORCE_RELOAD;
3519
3520         skinframe->stain = NULL;
3521         skinframe->merged = NULL;
3522         skinframe->base = NULL;
3523         skinframe->pants = NULL;
3524         skinframe->shirt = NULL;
3525         skinframe->nmap = NULL;
3526         skinframe->gloss = NULL;
3527         skinframe->glow = NULL;
3528         skinframe->fog = NULL;
3529         skinframe->reflect = NULL;
3530         skinframe->hasalpha = false;
3531
3532         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3533         if (!skindata)
3534                 return NULL;
3535
3536         if (developer_loading.integer)
3537                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3538
3539         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3540         {
3541                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3542                 temp2 = temp1 + width * height * 4;
3543                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3544                 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);
3545                 Mem_Free(temp1);
3546         }
3547         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3548         if (textureflags & TEXF_ALPHA)
3549         {
3550                 for (i = 3;i < width * height * 4;i += 4)
3551                 {
3552                         if (skindata[i] < 255)
3553                         {
3554                                 skinframe->hasalpha = true;
3555                                 break;
3556                         }
3557                 }
3558                 if (r_loadfog && skinframe->hasalpha)
3559                 {
3560                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3561                         memcpy(fogpixels, skindata, width * height * 4);
3562                         for (i = 0;i < width * height * 4;i += 4)
3563                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3564                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3565                         Mem_Free(fogpixels);
3566                 }
3567         }
3568
3569         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3570         //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]);
3571
3572         return skinframe;
3573 }
3574
3575 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3576 {
3577         int i;
3578         int featuresmask;
3579         skinframe_t *skinframe;
3580
3581         if (cls.state == ca_dedicated)
3582                 return NULL;
3583
3584         // if already loaded just return it, otherwise make a new skinframe
3585         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3586         if (skinframe->base)
3587                 return skinframe;
3588         //textureflags &= ~TEXF_FORCE_RELOAD;
3589
3590         skinframe->stain = NULL;
3591         skinframe->merged = NULL;
3592         skinframe->base = NULL;
3593         skinframe->pants = NULL;
3594         skinframe->shirt = NULL;
3595         skinframe->nmap = NULL;
3596         skinframe->gloss = NULL;
3597         skinframe->glow = NULL;
3598         skinframe->fog = NULL;
3599         skinframe->reflect = NULL;
3600         skinframe->hasalpha = false;
3601
3602         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3603         if (!skindata)
3604                 return NULL;
3605
3606         if (developer_loading.integer)
3607                 Con_Printf("loading quake skin \"%s\"\n", name);
3608
3609         // 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)
3610         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3611         memcpy(skinframe->qpixels, skindata, width*height);
3612         skinframe->qwidth = width;
3613         skinframe->qheight = height;
3614
3615         featuresmask = 0;
3616         for (i = 0;i < width * height;i++)
3617                 featuresmask |= palette_featureflags[skindata[i]];
3618
3619         skinframe->hasalpha = false;
3620         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3621         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3622         skinframe->qgeneratemerged = true;
3623         skinframe->qgeneratebase = skinframe->qhascolormapping;
3624         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3625
3626         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3627         //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]);
3628
3629         return skinframe;
3630 }
3631
3632 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3633 {
3634         int width;
3635         int height;
3636         unsigned char *skindata;
3637         char vabuf[1024];
3638
3639         if (!skinframe->qpixels)
3640                 return;
3641
3642         if (!skinframe->qhascolormapping)
3643                 colormapped = false;
3644
3645         if (colormapped)
3646         {
3647                 if (!skinframe->qgeneratebase)
3648                         return;
3649         }
3650         else
3651         {
3652                 if (!skinframe->qgeneratemerged)
3653                         return;
3654         }
3655
3656         width = skinframe->qwidth;
3657         height = skinframe->qheight;
3658         skindata = skinframe->qpixels;
3659
3660         if (skinframe->qgeneratenmap)
3661         {
3662                 unsigned char *temp1, *temp2;
3663                 skinframe->qgeneratenmap = false;
3664                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3665                 temp2 = temp1 + width * height * 4;
3666                 // use either a custom palette or the quake palette
3667                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3668                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3669                 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);
3670                 Mem_Free(temp1);
3671         }
3672
3673         if (skinframe->qgenerateglow)
3674         {
3675                 skinframe->qgenerateglow = false;
3676                 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
3677         }
3678
3679         if (colormapped)
3680         {
3681                 skinframe->qgeneratebase = false;
3682                 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);
3683                 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);
3684                 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);
3685         }
3686         else
3687         {
3688                 skinframe->qgeneratemerged = false;
3689                 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);
3690         }
3691
3692         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3693         {
3694                 Mem_Free(skinframe->qpixels);
3695                 skinframe->qpixels = NULL;
3696         }
3697 }
3698
3699 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)
3700 {
3701         int i;
3702         skinframe_t *skinframe;
3703         char vabuf[1024];
3704
3705         if (cls.state == ca_dedicated)
3706                 return NULL;
3707
3708         // if already loaded just return it, otherwise make a new skinframe
3709         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3710         if (skinframe->base)
3711                 return skinframe;
3712         textureflags &= ~TEXF_FORCE_RELOAD;
3713
3714         skinframe->stain = NULL;
3715         skinframe->merged = NULL;
3716         skinframe->base = NULL;
3717         skinframe->pants = NULL;
3718         skinframe->shirt = NULL;
3719         skinframe->nmap = NULL;
3720         skinframe->gloss = NULL;
3721         skinframe->glow = NULL;
3722         skinframe->fog = NULL;
3723         skinframe->reflect = NULL;
3724         skinframe->hasalpha = false;
3725
3726         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3727         if (!skindata)
3728                 return NULL;
3729
3730         if (developer_loading.integer)
3731                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3732
3733         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3734         if (textureflags & TEXF_ALPHA)
3735         {
3736                 for (i = 0;i < width * height;i++)
3737                 {
3738                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3739                         {
3740                                 skinframe->hasalpha = true;
3741                                 break;
3742                         }
3743                 }
3744                 if (r_loadfog && skinframe->hasalpha)
3745                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3746         }
3747
3748         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3749         //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]);
3750
3751         return skinframe;
3752 }
3753
3754 skinframe_t *R_SkinFrame_LoadMissing(void)
3755 {
3756         skinframe_t *skinframe;
3757
3758         if (cls.state == ca_dedicated)
3759                 return NULL;
3760
3761         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3762         skinframe->stain = NULL;
3763         skinframe->merged = NULL;
3764         skinframe->base = NULL;
3765         skinframe->pants = NULL;
3766         skinframe->shirt = NULL;
3767         skinframe->nmap = NULL;
3768         skinframe->gloss = NULL;
3769         skinframe->glow = NULL;
3770         skinframe->fog = NULL;
3771         skinframe->reflect = NULL;
3772         skinframe->hasalpha = false;
3773
3774         skinframe->avgcolor[0] = rand() / RAND_MAX;
3775         skinframe->avgcolor[1] = rand() / RAND_MAX;
3776         skinframe->avgcolor[2] = rand() / RAND_MAX;
3777         skinframe->avgcolor[3] = 1;
3778
3779         return skinframe;
3780 }
3781
3782 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3783 typedef struct suffixinfo_s
3784 {
3785         const char *suffix;
3786         qboolean flipx, flipy, flipdiagonal;
3787 }
3788 suffixinfo_t;
3789 static suffixinfo_t suffix[3][6] =
3790 {
3791         {
3792                 {"px",   false, false, false},
3793                 {"nx",   false, false, false},
3794                 {"py",   false, false, false},
3795                 {"ny",   false, false, false},
3796                 {"pz",   false, false, false},
3797                 {"nz",   false, false, false}
3798         },
3799         {
3800                 {"posx", false, false, false},
3801                 {"negx", false, false, false},
3802                 {"posy", false, false, false},
3803                 {"negy", false, false, false},
3804                 {"posz", false, false, false},
3805                 {"negz", false, false, false}
3806         },
3807         {
3808                 {"rt",    true, false,  true},
3809                 {"lf",   false,  true,  true},
3810                 {"ft",    true,  true, false},
3811                 {"bk",   false, false, false},
3812                 {"up",    true, false,  true},
3813                 {"dn",    true, false,  true}
3814         }
3815 };
3816
3817 static int componentorder[4] = {0, 1, 2, 3};
3818
3819 static rtexture_t *R_LoadCubemap(const char *basename)
3820 {
3821         int i, j, cubemapsize;
3822         unsigned char *cubemappixels, *image_buffer;
3823         rtexture_t *cubemaptexture;
3824         char name[256];
3825         // must start 0 so the first loadimagepixels has no requested width/height
3826         cubemapsize = 0;
3827         cubemappixels = NULL;
3828         cubemaptexture = NULL;
3829         // keep trying different suffix groups (posx, px, rt) until one loads
3830         for (j = 0;j < 3 && !cubemappixels;j++)
3831         {
3832                 // load the 6 images in the suffix group
3833                 for (i = 0;i < 6;i++)
3834                 {
3835                         // generate an image name based on the base and and suffix
3836                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3837                         // load it
3838                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3839                         {
3840                                 // an image loaded, make sure width and height are equal
3841                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3842                                 {
3843                                         // if this is the first image to load successfully, allocate the cubemap memory
3844                                         if (!cubemappixels && image_width >= 1)
3845                                         {
3846                                                 cubemapsize = image_width;
3847                                                 // note this clears to black, so unavailable sides are black
3848                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3849                                         }
3850                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3851                                         if (cubemappixels)
3852                                                 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);
3853                                 }
3854                                 else
3855                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3856                                 // free the image
3857                                 Mem_Free(image_buffer);
3858                         }
3859                 }
3860         }
3861         // if a cubemap loaded, upload it
3862         if (cubemappixels)
3863         {
3864                 if (developer_loading.integer)
3865                         Con_Printf("loading cubemap \"%s\"\n", basename);
3866
3867                 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);
3868                 Mem_Free(cubemappixels);
3869         }
3870         else
3871         {
3872                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3873                 if (developer_loading.integer)
3874                 {
3875                         Con_Printf("(tried tried images ");
3876                         for (j = 0;j < 3;j++)
3877                                 for (i = 0;i < 6;i++)
3878                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3879                         Con_Print(" and was unable to find any of them).\n");
3880                 }
3881         }
3882         return cubemaptexture;
3883 }
3884
3885 rtexture_t *R_GetCubemap(const char *basename)
3886 {
3887         int i;
3888         for (i = 0;i < r_texture_numcubemaps;i++)
3889                 if (r_texture_cubemaps[i] != NULL)
3890                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3891                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3892         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3893                 return r_texture_whitecube;
3894         r_texture_numcubemaps++;
3895         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3896         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3897         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3898         return r_texture_cubemaps[i]->texture;
3899 }
3900
3901 static void R_Main_FreeViewCache(void)
3902 {
3903         if (r_refdef.viewcache.entityvisible)
3904                 Mem_Free(r_refdef.viewcache.entityvisible);
3905         if (r_refdef.viewcache.world_pvsbits)
3906                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3907         if (r_refdef.viewcache.world_leafvisible)
3908                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3909         if (r_refdef.viewcache.world_surfacevisible)
3910                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3911         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3912 }
3913
3914 static void R_Main_ResizeViewCache(void)
3915 {
3916         int numentities = r_refdef.scene.numentities;
3917         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3918         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3919         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3920         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3921         if (r_refdef.viewcache.maxentities < numentities)
3922         {
3923                 r_refdef.viewcache.maxentities = numentities;
3924                 if (r_refdef.viewcache.entityvisible)
3925                         Mem_Free(r_refdef.viewcache.entityvisible);
3926                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3927         }
3928         if (r_refdef.viewcache.world_numclusters != numclusters)
3929         {
3930                 r_refdef.viewcache.world_numclusters = numclusters;
3931                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3932                 if (r_refdef.viewcache.world_pvsbits)
3933                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3934                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3935         }
3936         if (r_refdef.viewcache.world_numleafs != numleafs)
3937         {
3938                 r_refdef.viewcache.world_numleafs = numleafs;
3939                 if (r_refdef.viewcache.world_leafvisible)
3940                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3941                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3942         }
3943         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3944         {
3945                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3946                 if (r_refdef.viewcache.world_surfacevisible)
3947                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3948                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3949         }
3950 }
3951
3952 extern rtexture_t *loadingscreentexture;
3953 static void gl_main_start(void)
3954 {
3955         loadingscreentexture = NULL;
3956         r_texture_blanknormalmap = NULL;
3957         r_texture_white = NULL;
3958         r_texture_grey128 = NULL;
3959         r_texture_black = NULL;
3960         r_texture_whitecube = NULL;
3961         r_texture_normalizationcube = NULL;
3962         r_texture_fogattenuation = NULL;
3963         r_texture_fogheighttexture = NULL;
3964         r_texture_gammaramps = NULL;
3965         r_texture_numcubemaps = 0;
3966
3967         r_loaddds = r_texture_dds_load.integer != 0;
3968         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3969
3970         switch(vid.renderpath)
3971         {
3972         case RENDERPATH_GL20:
3973         case RENDERPATH_D3D9:
3974         case RENDERPATH_D3D10:
3975         case RENDERPATH_D3D11:
3976         case RENDERPATH_SOFT:
3977         case RENDERPATH_GLES2:
3978                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3979                 Cvar_SetValueQuick(&gl_combine, 1);
3980                 Cvar_SetValueQuick(&r_glsl, 1);
3981                 r_loadnormalmap = true;
3982                 r_loadgloss = true;
3983                 r_loadfog = false;
3984                 break;
3985         case RENDERPATH_GL13:
3986         case RENDERPATH_GLES1:
3987                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3988                 Cvar_SetValueQuick(&gl_combine, 1);
3989                 Cvar_SetValueQuick(&r_glsl, 0);
3990                 r_loadnormalmap = false;
3991                 r_loadgloss = false;
3992                 r_loadfog = true;
3993                 break;
3994         case RENDERPATH_GL11:
3995                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3996                 Cvar_SetValueQuick(&gl_combine, 0);
3997                 Cvar_SetValueQuick(&r_glsl, 0);
3998                 r_loadnormalmap = false;
3999                 r_loadgloss = false;
4000                 r_loadfog = true;
4001                 break;
4002         }
4003
4004         R_AnimCache_Free();
4005         R_FrameData_Reset();
4006
4007         r_numqueries = 0;
4008         r_maxqueries = 0;
4009         memset(r_queries, 0, sizeof(r_queries));
4010
4011         r_qwskincache = NULL;
4012         r_qwskincache_size = 0;
4013
4014         // due to caching of texture_t references, the collision cache must be reset
4015         Collision_Cache_Reset(true);
4016
4017         // set up r_skinframe loading system for textures
4018         memset(&r_skinframe, 0, sizeof(r_skinframe));
4019         r_skinframe.loadsequence = 1;
4020         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4021
4022         r_main_texturepool = R_AllocTexturePool();
4023         R_BuildBlankTextures();
4024         R_BuildNoTexture();
4025         if (vid.support.arb_texture_cube_map)
4026         {
4027                 R_BuildWhiteCube();
4028                 R_BuildNormalizationCube();
4029         }
4030         r_texture_fogattenuation = NULL;
4031         r_texture_fogheighttexture = NULL;
4032         r_texture_gammaramps = NULL;
4033         //r_texture_fogintensity = NULL;
4034         memset(&r_fb, 0, sizeof(r_fb));
4035         r_glsl_permutation = NULL;
4036         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4037         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4038         glslshaderstring = NULL;
4039 #ifdef SUPPORTD3D
4040         r_hlsl_permutation = NULL;
4041         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4042         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4043 #endif
4044         hlslshaderstring = NULL;
4045         memset(&r_svbsp, 0, sizeof (r_svbsp));
4046
4047         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4048         r_texture_numcubemaps = 0;
4049
4050         r_refdef.fogmasktable_density = 0;
4051 }
4052
4053 static void gl_main_shutdown(void)
4054 {
4055         R_AnimCache_Free();
4056         R_FrameData_Reset();
4057
4058         R_Main_FreeViewCache();
4059
4060         switch(vid.renderpath)
4061         {
4062         case RENDERPATH_GL11:
4063         case RENDERPATH_GL13:
4064         case RENDERPATH_GL20:
4065         case RENDERPATH_GLES1:
4066         case RENDERPATH_GLES2:
4067 #ifdef GL_SAMPLES_PASSED_ARB
4068                 if (r_maxqueries)
4069                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4070 #endif
4071                 break;
4072         case RENDERPATH_D3D9:
4073                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4074                 break;
4075         case RENDERPATH_D3D10:
4076                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4077                 break;
4078         case RENDERPATH_D3D11:
4079                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4080                 break;
4081         case RENDERPATH_SOFT:
4082                 break;
4083         }
4084
4085         r_numqueries = 0;
4086         r_maxqueries = 0;
4087         memset(r_queries, 0, sizeof(r_queries));
4088
4089         r_qwskincache = NULL;
4090         r_qwskincache_size = 0;
4091
4092         // clear out the r_skinframe state
4093         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4094         memset(&r_skinframe, 0, sizeof(r_skinframe));
4095
4096         if (r_svbsp.nodes)
4097                 Mem_Free(r_svbsp.nodes);
4098         memset(&r_svbsp, 0, sizeof (r_svbsp));
4099         R_FreeTexturePool(&r_main_texturepool);
4100         loadingscreentexture = NULL;
4101         r_texture_blanknormalmap = NULL;
4102         r_texture_white = NULL;
4103         r_texture_grey128 = NULL;
4104         r_texture_black = NULL;
4105         r_texture_whitecube = NULL;
4106         r_texture_normalizationcube = NULL;
4107         r_texture_fogattenuation = NULL;
4108         r_texture_fogheighttexture = NULL;
4109         r_texture_gammaramps = NULL;
4110         r_texture_numcubemaps = 0;
4111         //r_texture_fogintensity = NULL;
4112         memset(&r_fb, 0, sizeof(r_fb));
4113         R_GLSL_Restart_f();
4114
4115         r_glsl_permutation = NULL;
4116         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4117         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4118         glslshaderstring = NULL;
4119 #ifdef SUPPORTD3D
4120         r_hlsl_permutation = NULL;
4121         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4122         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4123 #endif
4124         hlslshaderstring = NULL;
4125 }
4126
4127 static void gl_main_newmap(void)
4128 {
4129         // FIXME: move this code to client
4130         char *entities, entname[MAX_QPATH];
4131         if (r_qwskincache)
4132                 Mem_Free(r_qwskincache);
4133         r_qwskincache = NULL;
4134         r_qwskincache_size = 0;
4135         if (cl.worldmodel)
4136         {
4137                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4138                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4139                 {
4140                         CL_ParseEntityLump(entities);
4141                         Mem_Free(entities);
4142                         return;
4143                 }
4144                 if (cl.worldmodel->brush.entities)
4145                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4146         }
4147         R_Main_FreeViewCache();
4148
4149         R_FrameData_Reset();
4150 }
4151
4152 void GL_Main_Init(void)
4153 {
4154         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4155
4156         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4157         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4158         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4159         if (gamemode == GAME_NEHAHRA)
4160         {
4161                 Cvar_RegisterVariable (&gl_fogenable);
4162                 Cvar_RegisterVariable (&gl_fogdensity);
4163                 Cvar_RegisterVariable (&gl_fogred);
4164                 Cvar_RegisterVariable (&gl_foggreen);
4165                 Cvar_RegisterVariable (&gl_fogblue);
4166                 Cvar_RegisterVariable (&gl_fogstart);
4167                 Cvar_RegisterVariable (&gl_fogend);
4168                 Cvar_RegisterVariable (&gl_skyclip);
4169         }
4170         Cvar_RegisterVariable(&r_motionblur);
4171         Cvar_RegisterVariable(&r_damageblur);
4172         Cvar_RegisterVariable(&r_motionblur_averaging);
4173         Cvar_RegisterVariable(&r_motionblur_randomize);
4174         Cvar_RegisterVariable(&r_motionblur_minblur);
4175         Cvar_RegisterVariable(&r_motionblur_maxblur);
4176         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4177         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4178         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4179         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4180         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4181         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4182         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4183         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4184         Cvar_RegisterVariable(&r_equalize_entities_by);
4185         Cvar_RegisterVariable(&r_equalize_entities_to);
4186         Cvar_RegisterVariable(&r_depthfirst);
4187         Cvar_RegisterVariable(&r_useinfinitefarclip);
4188         Cvar_RegisterVariable(&r_farclip_base);
4189         Cvar_RegisterVariable(&r_farclip_world);
4190         Cvar_RegisterVariable(&r_nearclip);
4191         Cvar_RegisterVariable(&r_deformvertexes);
4192         Cvar_RegisterVariable(&r_transparent);
4193         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4194         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4195         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4196         Cvar_RegisterVariable(&r_showoverdraw);
4197         Cvar_RegisterVariable(&r_showbboxes);
4198         Cvar_RegisterVariable(&r_showsurfaces);
4199         Cvar_RegisterVariable(&r_showtris);
4200         Cvar_RegisterVariable(&r_shownormals);
4201         Cvar_RegisterVariable(&r_showlighting);
4202         Cvar_RegisterVariable(&r_showshadowvolumes);
4203         Cvar_RegisterVariable(&r_showcollisionbrushes);
4204         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4205         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4206         Cvar_RegisterVariable(&r_showdisabledepthtest);
4207         Cvar_RegisterVariable(&r_drawportals);
4208         Cvar_RegisterVariable(&r_drawentities);
4209         Cvar_RegisterVariable(&r_draw2d);
4210         Cvar_RegisterVariable(&r_drawworld);
4211         Cvar_RegisterVariable(&r_cullentities_trace);
4212         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4213         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4214         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4215         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4216         Cvar_RegisterVariable(&r_sortentities);
4217         Cvar_RegisterVariable(&r_drawviewmodel);
4218         Cvar_RegisterVariable(&r_drawexteriormodel);
4219         Cvar_RegisterVariable(&r_speeds);
4220         Cvar_RegisterVariable(&r_fullbrights);
4221         Cvar_RegisterVariable(&r_wateralpha);
4222         Cvar_RegisterVariable(&r_dynamic);
4223         Cvar_RegisterVariable(&r_fakelight);
4224         Cvar_RegisterVariable(&r_fakelight_intensity);
4225         Cvar_RegisterVariable(&r_fullbright);
4226         Cvar_RegisterVariable(&r_shadows);
4227         Cvar_RegisterVariable(&r_shadows_darken);
4228         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4229         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4230         Cvar_RegisterVariable(&r_shadows_throwdistance);
4231         Cvar_RegisterVariable(&r_shadows_throwdirection);
4232         Cvar_RegisterVariable(&r_shadows_focus);
4233         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4234         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4235         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4236         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4237         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4238         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4239         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4240         Cvar_RegisterVariable(&r_fog_exp2);
4241         Cvar_RegisterVariable(&r_fog_clear);
4242         Cvar_RegisterVariable(&r_drawfog);
4243         Cvar_RegisterVariable(&r_transparentdepthmasking);
4244         Cvar_RegisterVariable(&r_transparent_sortmindist);
4245         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4246         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4247         Cvar_RegisterVariable(&r_texture_dds_load);
4248         Cvar_RegisterVariable(&r_texture_dds_save);
4249         Cvar_RegisterVariable(&r_textureunits);
4250         Cvar_RegisterVariable(&gl_combine);
4251         Cvar_RegisterVariable(&r_usedepthtextures);
4252         Cvar_RegisterVariable(&r_viewfbo);
4253         Cvar_RegisterVariable(&r_viewscale);
4254         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4255         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4256         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4257         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4258         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4259         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4260         Cvar_RegisterVariable(&r_glsl);
4261         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4262         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4263         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4264         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4265         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4266         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4267         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4268         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4269         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4270         Cvar_RegisterVariable(&r_glsl_postprocess);
4271         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4272         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4273         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4274         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4275         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4276         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4277         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4278         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4279         Cvar_RegisterVariable(&r_celshading);
4280         Cvar_RegisterVariable(&r_celoutlines);
4281
4282         Cvar_RegisterVariable(&r_water);
4283         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4284         Cvar_RegisterVariable(&r_water_clippingplanebias);
4285         Cvar_RegisterVariable(&r_water_refractdistort);
4286         Cvar_RegisterVariable(&r_water_reflectdistort);
4287         Cvar_RegisterVariable(&r_water_scissormode);
4288         Cvar_RegisterVariable(&r_water_lowquality);
4289         Cvar_RegisterVariable(&r_water_hideplayer);
4290         Cvar_RegisterVariable(&r_water_fbo);
4291
4292         Cvar_RegisterVariable(&r_lerpsprites);
4293         Cvar_RegisterVariable(&r_lerpmodels);
4294         Cvar_RegisterVariable(&r_lerplightstyles);
4295         Cvar_RegisterVariable(&r_waterscroll);
4296         Cvar_RegisterVariable(&r_bloom);
4297         Cvar_RegisterVariable(&r_bloom_colorscale);
4298         Cvar_RegisterVariable(&r_bloom_brighten);
4299         Cvar_RegisterVariable(&r_bloom_blur);
4300         Cvar_RegisterVariable(&r_bloom_resolution);
4301         Cvar_RegisterVariable(&r_bloom_colorexponent);
4302         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4303         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4304         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4305         Cvar_RegisterVariable(&r_hdr_glowintensity);
4306         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4307         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4308         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4309         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4310         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4311         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4312         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4313         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4314         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4315         Cvar_RegisterVariable(&developer_texturelogging);
4316         Cvar_RegisterVariable(&gl_lightmaps);
4317         Cvar_RegisterVariable(&r_test);
4318         Cvar_RegisterVariable(&r_glsl_saturation);
4319         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4320         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4321         Cvar_RegisterVariable(&r_framedatasize);
4322         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4323                 Cvar_SetValue("r_fullbrights", 0);
4324         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4325 }
4326
4327 void Render_Init(void)
4328 {
4329         gl_backend_init();
4330         R_Textures_Init();
4331         GL_Main_Init();
4332         Font_Init();
4333         GL_Draw_Init();
4334         R_Shadow_Init();
4335         R_Sky_Init();
4336         GL_Surf_Init();
4337         Sbar_Init();
4338         R_Particles_Init();
4339         R_Explosion_Init();
4340         R_LightningBeams_Init();
4341         Mod_RenderInit();
4342 }
4343
4344 /*
4345 ===============
4346 GL_Init
4347 ===============
4348 */
4349 #ifndef USE_GLES2
4350 extern char *ENGINE_EXTENSIONS;
4351 void GL_Init (void)
4352 {
4353         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4354         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4355         gl_version = (const char *)qglGetString(GL_VERSION);
4356         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4357
4358         if (!gl_extensions)
4359                 gl_extensions = "";
4360         if (!gl_platformextensions)
4361                 gl_platformextensions = "";
4362
4363         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4364         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4365         Con_Printf("GL_VERSION: %s\n", gl_version);
4366         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4367         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4368
4369         VID_CheckExtensions();
4370
4371         // LordHavoc: report supported extensions
4372         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4373
4374         // clear to black (loading plaque will be seen over this)
4375         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4376 }
4377 #endif
4378
4379 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4380 {
4381         int i;
4382         mplane_t *p;
4383         if (r_trippy.integer)
4384                 return false;
4385         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4386         {
4387                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4388                 if (i == 4)
4389                         continue;
4390                 p = r_refdef.view.frustum + i;
4391                 switch(p->signbits)
4392                 {
4393                 default:
4394                 case 0:
4395                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4396                                 return true;
4397                         break;
4398                 case 1:
4399                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4400                                 return true;
4401                         break;
4402                 case 2:
4403                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4404                                 return true;
4405                         break;
4406                 case 3:
4407                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4408                                 return true;
4409                         break;
4410                 case 4:
4411                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4412                                 return true;
4413                         break;
4414                 case 5:
4415                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4416                                 return true;
4417                         break;
4418                 case 6:
4419                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4420                                 return true;
4421                         break;
4422                 case 7:
4423                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4424                                 return true;
4425                         break;
4426                 }
4427         }
4428         return false;
4429 }
4430
4431 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4432 {
4433         int i;
4434         const mplane_t *p;
4435         if (r_trippy.integer)
4436                 return false;
4437         for (i = 0;i < numplanes;i++)
4438         {
4439                 p = planes + i;
4440                 switch(p->signbits)
4441                 {
4442                 default:
4443                 case 0:
4444                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 case 1:
4448                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 case 2:
4452                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 case 3:
4456                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 case 4:
4460                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4461                                 return true;
4462                         break;
4463                 case 5:
4464                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4465                                 return true;
4466                         break;
4467                 case 6:
4468                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4469                                 return true;
4470                         break;
4471                 case 7:
4472                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4473                                 return true;
4474                         break;
4475                 }
4476         }
4477         return false;
4478 }
4479
4480 //==================================================================================
4481
4482 // LordHavoc: this stores temporary data used within the same frame
4483
4484 typedef struct r_framedata_mem_s
4485 {
4486         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4487         size_t size; // how much usable space
4488         size_t current; // how much space in use
4489         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4490         size_t wantedsize; // how much space was allocated
4491         unsigned char *data; // start of real data (16byte aligned)
4492 }
4493 r_framedata_mem_t;
4494
4495 static r_framedata_mem_t *r_framedata_mem;
4496
4497 void R_FrameData_Reset(void)
4498 {
4499         while (r_framedata_mem)
4500         {
4501                 r_framedata_mem_t *next = r_framedata_mem->purge;
4502                 Mem_Free(r_framedata_mem);
4503                 r_framedata_mem = next;
4504         }
4505 }
4506
4507 static void R_FrameData_Resize(void)
4508 {
4509         size_t wantedsize;
4510         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4511         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4512         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4513         {
4514                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4515                 newmem->wantedsize = wantedsize;
4516                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4517                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4518                 newmem->current = 0;
4519                 newmem->mark = 0;
4520                 newmem->purge = r_framedata_mem;
4521                 r_framedata_mem = newmem;
4522         }
4523 }
4524
4525 void R_FrameData_NewFrame(void)
4526 {
4527         R_FrameData_Resize();
4528         if (!r_framedata_mem)
4529                 return;
4530         // if we ran out of space on the last frame, free the old memory now
4531         while (r_framedata_mem->purge)
4532         {
4533                 // repeatedly remove the second item in the list, leaving only head
4534                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4535                 Mem_Free(r_framedata_mem->purge);
4536                 r_framedata_mem->purge = next;
4537         }
4538         // reset the current mem pointer
4539         r_framedata_mem->current = 0;
4540         r_framedata_mem->mark = 0;
4541 }
4542
4543 void *R_FrameData_Alloc(size_t size)
4544 {
4545         void *data;
4546
4547         // align to 16 byte boundary - the data pointer is already aligned, so we
4548         // only need to ensure the size of every allocation is also aligned
4549         size = (size + 15) & ~15;
4550
4551         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4552         {
4553                 // emergency - we ran out of space, allocate more memory
4554                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4555                 R_FrameData_Resize();
4556         }
4557
4558         data = r_framedata_mem->data + r_framedata_mem->current;
4559         r_framedata_mem->current += size;
4560
4561         // count the usage for stats
4562         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4563         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4564
4565         return (void *)data;
4566 }
4567
4568 void *R_FrameData_Store(size_t size, void *data)
4569 {
4570         void *d = R_FrameData_Alloc(size);
4571         if (d && data)
4572                 memcpy(d, data, size);
4573         return d;
4574 }
4575
4576 void R_FrameData_SetMark(void)
4577 {
4578         if (!r_framedata_mem)
4579                 return;
4580         r_framedata_mem->mark = r_framedata_mem->current;
4581 }
4582
4583 void R_FrameData_ReturnToMark(void)
4584 {
4585         if (!r_framedata_mem)
4586                 return;
4587         r_framedata_mem->current = r_framedata_mem->mark;
4588 }
4589
4590 //==================================================================================
4591
4592 // LordHavoc: animcache originally written by Echon, rewritten since then
4593
4594 /**
4595  * Animation cache prevents re-generating mesh data for an animated model
4596  * multiple times in one frame for lighting, shadowing, reflections, etc.
4597  */
4598
4599 void R_AnimCache_Free(void)
4600 {
4601 }
4602
4603 void R_AnimCache_ClearCache(void)
4604 {
4605         int i;
4606         entity_render_t *ent;
4607
4608         for (i = 0;i < r_refdef.scene.numentities;i++)
4609         {
4610                 ent = r_refdef.scene.entities[i];
4611                 ent->animcache_vertex3f = NULL;
4612                 ent->animcache_normal3f = NULL;
4613                 ent->animcache_svector3f = NULL;
4614                 ent->animcache_tvector3f = NULL;
4615                 ent->animcache_vertexmesh = NULL;
4616                 ent->animcache_vertex3fbuffer = NULL;
4617                 ent->animcache_vertexmeshbuffer = NULL;
4618         }
4619 }
4620
4621 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4622 {
4623         int i;
4624
4625         // check if we need the meshbuffers
4626         if (!vid.useinterleavedarrays)
4627                 return;
4628
4629         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4630                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4631         // TODO: upload vertex3f buffer?
4632         if (ent->animcache_vertexmesh)
4633         {
4634                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4635                 for (i = 0;i < numvertices;i++)
4636                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4637                 if (ent->animcache_svector3f)
4638                         for (i = 0;i < numvertices;i++)
4639                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4640                 if (ent->animcache_tvector3f)
4641                         for (i = 0;i < numvertices;i++)
4642                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4643                 if (ent->animcache_normal3f)
4644                         for (i = 0;i < numvertices;i++)
4645                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4646                 // TODO: upload vertexmeshbuffer?
4647         }
4648 }
4649
4650 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4651 {
4652         dp_model_t *model = ent->model;
4653         int numvertices;
4654         // see if it's already cached this frame
4655         if (ent->animcache_vertex3f)
4656         {
4657                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4658                 if (wantnormals || wanttangents)
4659                 {
4660                         if (ent->animcache_normal3f)
4661                                 wantnormals = false;
4662                         if (ent->animcache_svector3f)
4663                                 wanttangents = false;
4664                         if (wantnormals || wanttangents)
4665                         {
4666                                 numvertices = model->surfmesh.num_vertices;
4667                                 if (wantnormals)
4668                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4669                                 if (wanttangents)
4670                                 {
4671                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4672                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4673                                 }
4674                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4675                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4676                         }
4677                 }
4678         }
4679         else
4680         {
4681                 // see if this ent is worth caching
4682                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4683                         return false;
4684                 // get some memory for this entity and generate mesh data
4685                 numvertices = model->surfmesh.num_vertices;
4686                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4687                 if (wantnormals)
4688                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4689                 if (wanttangents)
4690                 {
4691                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4692                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4693                 }
4694                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4695                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4696         }
4697         return true;
4698 }
4699
4700 void R_AnimCache_CacheVisibleEntities(void)
4701 {
4702         int i;
4703         qboolean wantnormals = true;
4704         qboolean wanttangents = !r_showsurfaces.integer;
4705
4706         switch(vid.renderpath)
4707         {
4708         case RENDERPATH_GL20:
4709         case RENDERPATH_D3D9:
4710         case RENDERPATH_D3D10:
4711         case RENDERPATH_D3D11:
4712         case RENDERPATH_GLES2:
4713                 break;
4714         case RENDERPATH_GL11:
4715         case RENDERPATH_GL13:
4716         case RENDERPATH_GLES1:
4717                 wanttangents = false;
4718                 break;
4719         case RENDERPATH_SOFT:
4720                 break;
4721         }
4722
4723         if (r_shownormals.integer)
4724                 wanttangents = wantnormals = true;
4725
4726         // TODO: thread this
4727         // NOTE: R_PrepareRTLights() also caches entities
4728
4729         for (i = 0;i < r_refdef.scene.numentities;i++)
4730                 if (r_refdef.viewcache.entityvisible[i])
4731                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4732 }
4733
4734 //==================================================================================
4735
4736 extern cvar_t r_overheadsprites_pushback;
4737
4738 static void R_View_UpdateEntityLighting (void)
4739 {
4740         int i;
4741         entity_render_t *ent;
4742         vec3_t tempdiffusenormal, avg;
4743         vec_t f, fa, fd, fdd;
4744         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4745
4746         for (i = 0;i < r_refdef.scene.numentities;i++)
4747         {
4748                 ent = r_refdef.scene.entities[i];
4749
4750                 // skip unseen models
4751                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4752                         continue;
4753
4754                 // skip bsp models
4755                 if (ent->model && ent->model == cl.worldmodel)
4756                 {
4757                         // TODO: use modellight for r_ambient settings on world?
4758                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4759                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4760                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4761                         continue;
4762                 }
4763                 
4764                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4765                 {
4766                         // aleady updated by CSQC
4767                         // TODO: force modellight on BSP models in this case?
4768                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4769                 }
4770                 else
4771                 {
4772                         // fetch the lighting from the worldmodel data
4773                         VectorClear(ent->modellight_ambient);
4774                         VectorClear(ent->modellight_diffuse);
4775                         VectorClear(tempdiffusenormal);
4776                         if (ent->flags & RENDER_LIGHT)
4777                         {
4778                                 vec3_t org;
4779                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4780
4781                                 // complete lightning for lit sprites
4782                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4783                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4784                                 {
4785                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4786                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4787                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4788                                 }
4789                                 else
4790                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4791
4792                                 if(ent->flags & RENDER_EQUALIZE)
4793                                 {
4794                                         // first fix up ambient lighting...
4795                                         if(r_equalize_entities_minambient.value > 0)
4796                                         {
4797                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4798                                                 if(fd > 0)
4799                                                 {
4800                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4801                                                         if(fa < r_equalize_entities_minambient.value * fd)
4802                                                         {
4803                                                                 // solve:
4804                                                                 //   fa'/fd' = minambient
4805                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4806                                                                 //   ...
4807                                                                 //   fa' = fd' * minambient
4808                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4809                                                                 //   ...
4810                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4811                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4812                                                                 //   ...
4813                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4814                                                                 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
4815                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4816                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4817                                                         }
4818                                                 }
4819                                         }
4820
4821                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4822                                         {
4823                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4824                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4825                                                 f = fa + 0.25 * fd;
4826                                                 if(f > 0)
4827                                                 {
4828                                                         // adjust brightness and saturation to target
4829                                                         avg[0] = avg[1] = avg[2] = fa / f;
4830                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4831                                                         avg[0] = avg[1] = avg[2] = fd / f;
4832                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4833                                                 }
4834                                         }
4835                                 }
4836                         }
4837                         else // highly rare
4838                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4839                 }
4840
4841                 // move the light direction into modelspace coordinates for lighting code
4842                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4843                 if(VectorLength2(ent->modellight_lightdir) == 0)
4844                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4845                 VectorNormalize(ent->modellight_lightdir);
4846         }
4847 }
4848
4849 #define MAX_LINEOFSIGHTTRACES 64
4850
4851 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4852 {
4853         int i;
4854         vec3_t boxmins, boxmaxs;
4855         vec3_t start;
4856         vec3_t end;
4857         dp_model_t *model = r_refdef.scene.worldmodel;
4858
4859         if (!model || !model->brush.TraceLineOfSight)
4860                 return true;
4861
4862         // expand the box a little
4863         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4864         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4865         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4866         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4867         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4868         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4869
4870         // return true if eye is inside enlarged box
4871         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4872                 return true;
4873
4874         // try center
4875         VectorCopy(eye, start);
4876         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4877         if (model->brush.TraceLineOfSight(model, start, end))
4878                 return true;
4879
4880         // try various random positions
4881         for (i = 0;i < numsamples;i++)
4882         {
4883                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4884                 if (model->brush.TraceLineOfSight(model, start, end))
4885                         return true;
4886         }
4887
4888         return false;
4889 }
4890
4891
4892 static void R_View_UpdateEntityVisible (void)
4893 {
4894         int i;
4895         int renderimask;
4896         int samples;
4897         entity_render_t *ent;
4898
4899         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4900                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4901                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4902                 :                                                          RENDER_EXTERIORMODEL;
4903         if (!r_drawviewmodel.integer)
4904                 renderimask |= RENDER_VIEWMODEL;
4905         if (!r_drawexteriormodel.integer)
4906                 renderimask |= RENDER_EXTERIORMODEL;
4907         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4908         {
4909                 // worldmodel can check visibility
4910                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4911                 for (i = 0;i < r_refdef.scene.numentities;i++)
4912                 {
4913                         ent = r_refdef.scene.entities[i];
4914                         if (!(ent->flags & renderimask))
4915                         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)))
4916                         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))
4917                                 r_refdef.viewcache.entityvisible[i] = true;
4918                 }
4919         }
4920         else
4921         {
4922                 // no worldmodel or it can't check visibility
4923                 for (i = 0;i < r_refdef.scene.numentities;i++)
4924                 {
4925                         ent = r_refdef.scene.entities[i];
4926                         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));
4927                 }
4928         }
4929         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4930                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4931         {
4932                 for (i = 0;i < r_refdef.scene.numentities;i++)
4933                 {
4934                         if (!r_refdef.viewcache.entityvisible[i])
4935                                 continue;
4936                         ent = r_refdef.scene.entities[i];
4937                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4938                         {
4939                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4940                                 if (samples < 0)
4941                                         continue; // temp entities do pvs only
4942                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4943                                         ent->last_trace_visibility = realtime;
4944                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4945                                         r_refdef.viewcache.entityvisible[i] = 0;
4946                         }
4947                 }
4948         }
4949 }
4950
4951 /// only used if skyrendermasked, and normally returns false
4952 static int R_DrawBrushModelsSky (void)
4953 {
4954         int i, sky;
4955         entity_render_t *ent;
4956
4957         sky = false;
4958         for (i = 0;i < r_refdef.scene.numentities;i++)
4959         {
4960                 if (!r_refdef.viewcache.entityvisible[i])
4961                         continue;
4962                 ent = r_refdef.scene.entities[i];
4963                 if (!ent->model || !ent->model->DrawSky)
4964                         continue;
4965                 ent->model->DrawSky(ent);
4966                 sky = true;
4967         }
4968         return sky;
4969 }
4970
4971 static void R_DrawNoModel(entity_render_t *ent);
4972 static void R_DrawModels(void)
4973 {
4974         int i;
4975         entity_render_t *ent;
4976
4977         for (i = 0;i < r_refdef.scene.numentities;i++)
4978         {
4979                 if (!r_refdef.viewcache.entityvisible[i])
4980                         continue;
4981                 ent = r_refdef.scene.entities[i];
4982                 r_refdef.stats.entities++;
4983                 /*
4984                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4985                 {
4986                         vec3_t f, l, u, o;
4987                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4988                         Con_Printf("R_DrawModels\n");
4989                         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]);
4990                         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);
4991                         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);
4992                 }
4993                 */
4994                 if (ent->model && ent->model->Draw != NULL)
4995                         ent->model->Draw(ent);
4996                 else
4997                         R_DrawNoModel(ent);
4998         }
4999 }
5000
5001 static void R_DrawModelsDepth(void)
5002 {
5003         int i;
5004         entity_render_t *ent;
5005
5006         for (i = 0;i < r_refdef.scene.numentities;i++)
5007         {
5008                 if (!r_refdef.viewcache.entityvisible[i])
5009                         continue;
5010                 ent = r_refdef.scene.entities[i];
5011                 if (ent->model && ent->model->DrawDepth != NULL)
5012                         ent->model->DrawDepth(ent);
5013         }
5014 }
5015
5016 static void R_DrawModelsDebug(void)
5017 {
5018         int i;
5019         entity_render_t *ent;
5020
5021         for (i = 0;i < r_refdef.scene.numentities;i++)
5022         {
5023                 if (!r_refdef.viewcache.entityvisible[i])
5024                         continue;
5025                 ent = r_refdef.scene.entities[i];
5026                 if (ent->model && ent->model->DrawDebug != NULL)
5027                         ent->model->DrawDebug(ent);
5028         }
5029 }
5030
5031 static void R_DrawModelsAddWaterPlanes(void)
5032 {
5033         int i;
5034         entity_render_t *ent;
5035
5036         for (i = 0;i < r_refdef.scene.numentities;i++)
5037         {
5038                 if (!r_refdef.viewcache.entityvisible[i])
5039                         continue;
5040                 ent = r_refdef.scene.entities[i];
5041                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5042                         ent->model->DrawAddWaterPlanes(ent);
5043         }
5044 }
5045
5046 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}};
5047
5048 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5049 {
5050         if (r_hdr_irisadaptation.integer)
5051         {
5052                 vec3_t p;
5053                 vec3_t ambient;
5054                 vec3_t diffuse;
5055                 vec3_t diffusenormal;
5056                 vec3_t forward;
5057                 vec_t brightness = 0.0f;
5058                 vec_t goal;
5059                 vec_t current;
5060                 vec_t d;
5061                 int c;
5062                 VectorCopy(r_refdef.view.forward, forward);
5063                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5064                 {
5065                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5066                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5067                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5068                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5069                         d = DotProduct(forward, diffusenormal);
5070                         brightness += VectorLength(ambient);
5071                         if (d > 0)
5072                                 brightness += d * VectorLength(diffuse);
5073                 }
5074                 brightness *= 1.0f / c;
5075                 brightness += 0.00001f; // make sure it's never zero
5076                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5077                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5078                 current = r_hdr_irisadaptation_value.value;
5079                 if (current < goal)
5080                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5081                 else if (current > goal)
5082                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5083                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5084                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5085         }
5086         else if (r_hdr_irisadaptation_value.value != 1.0f)
5087                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5088 }
5089
5090 static void R_View_SetFrustum(const int *scissor)
5091 {
5092         int i;
5093         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5094         vec3_t forward, left, up, origin, v;
5095
5096         if(scissor)
5097         {
5098                 // flipped x coordinates (because x points left here)
5099                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5100                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5101
5102                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5103                 switch(vid.renderpath)
5104                 {
5105                         case RENDERPATH_D3D9:
5106                         case RENDERPATH_D3D10:
5107                         case RENDERPATH_D3D11:
5108                                 // non-flipped y coordinates
5109                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5110                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5111                                 break;
5112                         case RENDERPATH_SOFT:
5113                         case RENDERPATH_GL11:
5114                         case RENDERPATH_GL13:
5115                         case RENDERPATH_GL20:
5116                         case RENDERPATH_GLES1:
5117                         case RENDERPATH_GLES2:
5118                                 // non-flipped y coordinates
5119                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5120                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5121                                 break;
5122                 }
5123         }
5124
5125         // we can't trust r_refdef.view.forward and friends in reflected scenes
5126         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5127
5128 #if 0
5129         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5130         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5131         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5132         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5133         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5134         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5135         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5136         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5137         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5138         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5139         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5140         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5141 #endif
5142
5143 #if 0
5144         zNear = r_refdef.nearclip;
5145         nudge = 1.0 - 1.0 / (1<<23);
5146         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5147         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5148         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5149         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5150         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5151         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5152         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5153         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5154 #endif
5155
5156
5157
5158 #if 0
5159         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5160         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5161         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5162         r_refdef.view.frustum[0].dist = m[15] - m[12];
5163
5164         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5165         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5166         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5167         r_refdef.view.frustum[1].dist = m[15] + m[12];
5168
5169         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5170         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5171         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5172         r_refdef.view.frustum[2].dist = m[15] - m[13];
5173
5174         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5175         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5176         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5177         r_refdef.view.frustum[3].dist = m[15] + m[13];
5178
5179         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5180         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5181         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5182         r_refdef.view.frustum[4].dist = m[15] - m[14];
5183
5184         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5185         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5186         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5187         r_refdef.view.frustum[5].dist = m[15] + m[14];
5188 #endif
5189
5190         if (r_refdef.view.useperspective)
5191         {
5192                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5193                 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]);
5194                 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]);
5195                 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]);
5196                 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]);
5197
5198                 // then the normals from the corners relative to origin
5199                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5200                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5201                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5202                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5203
5204                 // in a NORMAL view, forward cross left == up
5205                 // in a REFLECTED view, forward cross left == down
5206                 // so our cross products above need to be adjusted for a left handed coordinate system
5207                 CrossProduct(forward, left, v);
5208                 if(DotProduct(v, up) < 0)
5209                 {
5210                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5211                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5212                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5213                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5214                 }
5215
5216                 // Leaving those out was a mistake, those were in the old code, and they
5217                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5218                 // I couldn't reproduce it after adding those normalizations. --blub
5219                 VectorNormalize(r_refdef.view.frustum[0].normal);
5220                 VectorNormalize(r_refdef.view.frustum[1].normal);
5221                 VectorNormalize(r_refdef.view.frustum[2].normal);
5222                 VectorNormalize(r_refdef.view.frustum[3].normal);
5223
5224                 // make the corners absolute
5225                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5226                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5227                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5228                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5229
5230                 // one more normal
5231                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5232
5233                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5234                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5235                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5236                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5237                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5238         }
5239         else
5240         {
5241                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5242                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5243                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5244                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5245                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5246                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5247                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5248                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5249                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5250                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5251         }
5252         r_refdef.view.numfrustumplanes = 5;
5253
5254         if (r_refdef.view.useclipplane)
5255         {
5256                 r_refdef.view.numfrustumplanes = 6;
5257                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5258         }
5259
5260         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5261                 PlaneClassify(r_refdef.view.frustum + i);
5262
5263         // LordHavoc: note to all quake engine coders, Quake had a special case
5264         // for 90 degrees which assumed a square view (wrong), so I removed it,
5265         // Quake2 has it disabled as well.
5266
5267         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5268         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5269         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5270         //PlaneClassify(&frustum[0]);
5271
5272         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5273         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5274         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5275         //PlaneClassify(&frustum[1]);
5276
5277         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5278         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5279         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5280         //PlaneClassify(&frustum[2]);
5281
5282         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5283         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5284         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5285         //PlaneClassify(&frustum[3]);
5286
5287         // nearclip plane
5288         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5289         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5290         //PlaneClassify(&frustum[4]);
5291 }
5292
5293 static void R_View_UpdateWithScissor(const int *myscissor)
5294 {
5295         R_Main_ResizeViewCache();
5296         R_View_SetFrustum(myscissor);
5297         R_View_WorldVisibility(r_refdef.view.useclipplane);
5298         R_View_UpdateEntityVisible();
5299         R_View_UpdateEntityLighting();
5300 }
5301
5302 static void R_View_Update(void)
5303 {
5304         R_Main_ResizeViewCache();
5305         R_View_SetFrustum(NULL);
5306         R_View_WorldVisibility(r_refdef.view.useclipplane);
5307         R_View_UpdateEntityVisible();
5308         R_View_UpdateEntityLighting();
5309 }
5310
5311 float viewscalefpsadjusted = 1.0f;
5312
5313 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5314 {
5315         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5316         scale = bound(0.03125f, scale, 1.0f);
5317         *outwidth = (int)ceil(width * scale);
5318         *outheight = (int)ceil(height * scale);
5319 }
5320
5321 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5322 {
5323         const float *customclipplane = NULL;
5324         float plane[4];
5325         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5326         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5327         {
5328                 // LordHavoc: couldn't figure out how to make this approach the
5329                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5330                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5331                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5332                         dist = r_refdef.view.clipplane.dist;
5333                 plane[0] = r_refdef.view.clipplane.normal[0];
5334                 plane[1] = r_refdef.view.clipplane.normal[1];
5335                 plane[2] = r_refdef.view.clipplane.normal[2];
5336                 plane[3] = -dist;
5337                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5338         }
5339
5340         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5341         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5342
5343         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5344         if (!r_refdef.view.useperspective)
5345                 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);
5346         else if (vid.stencil && r_useinfinitefarclip.integer)
5347                 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);
5348         else
5349                 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);
5350         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5351         R_SetViewport(&r_refdef.view.viewport);
5352         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5353         {
5354                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5355                 float screenplane[4];
5356                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5357                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5358                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5359                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5360                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5361         }
5362 }
5363
5364 void R_EntityMatrix(const matrix4x4_t *matrix)
5365 {
5366         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5367         {
5368                 gl_modelmatrixchanged = false;
5369                 gl_modelmatrix = *matrix;
5370                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5371                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5372                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5373                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5374                 CHECKGLERROR
5375                 switch(vid.renderpath)
5376                 {
5377                 case RENDERPATH_D3D9:
5378 #ifdef SUPPORTD3D
5379                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5380                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5381 #endif
5382                         break;
5383                 case RENDERPATH_D3D10:
5384                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5385                         break;
5386                 case RENDERPATH_D3D11:
5387                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5388                         break;
5389                 case RENDERPATH_GL11:
5390                 case RENDERPATH_GL13:
5391                 case RENDERPATH_GLES1:
5392                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5393                         break;
5394                 case RENDERPATH_SOFT:
5395                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5396                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5397                         break;
5398                 case RENDERPATH_GL20:
5399                 case RENDERPATH_GLES2:
5400                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5401                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5402                         break;
5403                 }
5404         }
5405 }
5406
5407 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5408 {
5409         r_viewport_t viewport;
5410
5411         CHECKGLERROR
5412
5413         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5414         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);
5415         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5416         R_SetViewport(&viewport);
5417         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5418         GL_Color(1, 1, 1, 1);
5419         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5420         GL_BlendFunc(GL_ONE, GL_ZERO);
5421         GL_ScissorTest(false);
5422         GL_DepthMask(false);
5423         GL_DepthRange(0, 1);
5424         GL_DepthTest(false);
5425         GL_DepthFunc(GL_LEQUAL);
5426         R_EntityMatrix(&identitymatrix);
5427         R_Mesh_ResetTextureState();
5428         GL_PolygonOffset(0, 0);
5429         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5430         switch(vid.renderpath)
5431         {
5432         case RENDERPATH_GL11:
5433         case RENDERPATH_GL13:
5434         case RENDERPATH_GL20:
5435         case RENDERPATH_GLES1:
5436         case RENDERPATH_GLES2:
5437                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5438                 break;
5439         case RENDERPATH_D3D9:
5440         case RENDERPATH_D3D10:
5441         case RENDERPATH_D3D11:
5442         case RENDERPATH_SOFT:
5443                 break;
5444         }
5445         GL_CullFace(GL_NONE);
5446
5447         CHECKGLERROR
5448 }
5449
5450 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5451 {
5452         DrawQ_Finish();
5453
5454         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5455 }
5456
5457 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5458 {
5459         DrawQ_Finish();
5460
5461         R_SetupView(true, fbo, depthtexture, colortexture);
5462         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5463         GL_Color(1, 1, 1, 1);
5464         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5465         GL_BlendFunc(GL_ONE, GL_ZERO);
5466         GL_ScissorTest(true);
5467         GL_DepthMask(true);
5468         GL_DepthRange(0, 1);
5469         GL_DepthTest(true);
5470         GL_DepthFunc(GL_LEQUAL);
5471         R_EntityMatrix(&identitymatrix);
5472         R_Mesh_ResetTextureState();
5473         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5474         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5475         switch(vid.renderpath)
5476         {
5477         case RENDERPATH_GL11:
5478         case RENDERPATH_GL13:
5479         case RENDERPATH_GL20:
5480         case RENDERPATH_GLES1:
5481         case RENDERPATH_GLES2:
5482                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5483                 break;
5484         case RENDERPATH_D3D9:
5485         case RENDERPATH_D3D10:
5486         case RENDERPATH_D3D11:
5487         case RENDERPATH_SOFT:
5488                 break;
5489         }
5490         GL_CullFace(r_refdef.view.cullface_back);
5491 }
5492
5493 /*
5494 ================
5495 R_RenderView_UpdateViewVectors
5496 ================
5497 */
5498 void R_RenderView_UpdateViewVectors(void)
5499 {
5500         // break apart the view matrix into vectors for various purposes
5501         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5502         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5503         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5504         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5505         // make an inverted copy of the view matrix for tracking sprites
5506         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5507 }
5508
5509 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5510 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5511
5512 static void R_Water_StartFrame(void)
5513 {
5514         int i;
5515         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5516         r_waterstate_waterplane_t *p;
5517         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5518
5519         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5520                 return;
5521
5522         switch(vid.renderpath)
5523         {
5524         case RENDERPATH_GL20:
5525         case RENDERPATH_D3D9:
5526         case RENDERPATH_D3D10:
5527         case RENDERPATH_D3D11:
5528         case RENDERPATH_SOFT:
5529         case RENDERPATH_GLES2:
5530                 break;
5531         case RENDERPATH_GL11:
5532         case RENDERPATH_GL13:
5533         case RENDERPATH_GLES1:
5534                 return;
5535         }
5536
5537         // set waterwidth and waterheight to the water resolution that will be
5538         // used (often less than the screen resolution for faster rendering)
5539         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5540
5541         // calculate desired texture sizes
5542         // can't use water if the card does not support the texture size
5543         if (!r_water.integer || r_showsurfaces.integer)
5544                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5545         else if (vid.support.arb_texture_non_power_of_two)
5546         {
5547                 texturewidth = waterwidth;
5548                 textureheight = waterheight;
5549                 camerawidth = waterwidth;
5550                 cameraheight = waterheight;
5551         }
5552         else
5553         {
5554                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5555                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5556                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5557                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5558         }
5559
5560         // allocate textures as needed
5561         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))
5562         {
5563                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5564                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5565                 {
5566                         if (p->texture_refraction)
5567                                 R_FreeTexture(p->texture_refraction);
5568                         p->texture_refraction = NULL;
5569                         if (p->fbo_refraction)
5570                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5571                         p->fbo_refraction = 0;
5572                         if (p->texture_reflection)
5573                                 R_FreeTexture(p->texture_reflection);
5574                         p->texture_reflection = NULL;
5575                         if (p->fbo_reflection)
5576                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5577                         p->fbo_reflection = 0;
5578                         if (p->texture_camera)
5579                                 R_FreeTexture(p->texture_camera);
5580                         p->texture_camera = NULL;
5581                         if (p->fbo_camera)
5582                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5583                         p->fbo_camera = 0;
5584                 }
5585                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5586                 r_fb.water.texturewidth = texturewidth;
5587                 r_fb.water.textureheight = textureheight;
5588                 r_fb.water.camerawidth = camerawidth;
5589                 r_fb.water.cameraheight = cameraheight;
5590         }
5591
5592         if (r_fb.water.texturewidth)
5593         {
5594                 int scaledwidth, scaledheight;
5595
5596                 r_fb.water.enabled = true;
5597
5598                 // water resolution is usually reduced
5599                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5600                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5601                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5602
5603                 // set up variables that will be used in shader setup
5604                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5605                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5606                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5607                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5608         }
5609
5610         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5611         r_fb.water.numwaterplanes = 0;
5612 }
5613
5614 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5615 {
5616         int planeindex, bestplaneindex, vertexindex;
5617         vec3_t mins, maxs, normal, center, v, n;
5618         vec_t planescore, bestplanescore;
5619         mplane_t plane;
5620         r_waterstate_waterplane_t *p;
5621         texture_t *t = R_GetCurrentTexture(surface->texture);
5622
5623         rsurface.texture = t;
5624         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5625         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5626         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5627                 return;
5628         // average the vertex normals, find the surface bounds (after deformvertexes)
5629         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5630         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5631         VectorCopy(n, normal);
5632         VectorCopy(v, mins);
5633         VectorCopy(v, maxs);
5634         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5635         {
5636                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5637                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5638                 VectorAdd(normal, n, normal);
5639                 mins[0] = min(mins[0], v[0]);
5640                 mins[1] = min(mins[1], v[1]);
5641                 mins[2] = min(mins[2], v[2]);
5642                 maxs[0] = max(maxs[0], v[0]);
5643                 maxs[1] = max(maxs[1], v[1]);
5644                 maxs[2] = max(maxs[2], v[2]);
5645         }
5646         VectorNormalize(normal);
5647         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5648
5649         VectorCopy(normal, plane.normal);
5650         VectorNormalize(plane.normal);
5651         plane.dist = DotProduct(center, plane.normal);
5652         PlaneClassify(&plane);
5653         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5654         {
5655                 // skip backfaces (except if nocullface is set)
5656 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5657 //                      return;
5658                 VectorNegate(plane.normal, plane.normal);
5659                 plane.dist *= -1;
5660                 PlaneClassify(&plane);
5661         }
5662
5663
5664         // find a matching plane if there is one
5665         bestplaneindex = -1;
5666         bestplanescore = 1048576.0f;
5667         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5668         {
5669                 if(p->camera_entity == t->camera_entity)
5670                 {
5671                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5672                         if (bestplaneindex < 0 || bestplanescore > planescore)
5673                         {
5674                                 bestplaneindex = planeindex;
5675                                 bestplanescore = planescore;
5676                         }
5677                 }
5678         }
5679         planeindex = bestplaneindex;
5680         p = r_fb.water.waterplanes + planeindex;
5681
5682         // if this surface does not fit any known plane rendered this frame, add one
5683         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5684         {
5685                 // store the new plane
5686                 planeindex = r_fb.water.numwaterplanes++;
5687                 p = r_fb.water.waterplanes + planeindex;
5688                 p->plane = plane;
5689                 // clear materialflags and pvs
5690                 p->materialflags = 0;
5691                 p->pvsvalid = false;
5692                 p->camera_entity = t->camera_entity;
5693                 VectorCopy(mins, p->mins);
5694                 VectorCopy(maxs, p->maxs);
5695         }
5696         else
5697         {
5698                 // merge mins/maxs when we're adding this surface to the plane
5699                 p->mins[0] = min(p->mins[0], mins[0]);
5700                 p->mins[1] = min(p->mins[1], mins[1]);
5701                 p->mins[2] = min(p->mins[2], mins[2]);
5702                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5703                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5704                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5705         }
5706         // merge this surface's materialflags into the waterplane
5707         p->materialflags |= t->currentmaterialflags;
5708         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5709         {
5710                 // merge this surface's PVS into the waterplane
5711                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5712                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5713                 {
5714                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5715                         p->pvsvalid = true;
5716                 }
5717         }
5718 }
5719
5720 extern cvar_t r_drawparticles;
5721 extern cvar_t r_drawdecals;
5722
5723 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5724 {
5725         int myscissor[4];
5726         r_refdef_view_t originalview;
5727         r_refdef_view_t myview;
5728         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;
5729         r_waterstate_waterplane_t *p;
5730         vec3_t visorigin;
5731         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5732         char vabuf[1024];
5733
5734         originalview = r_refdef.view;
5735
5736         // lowquality hack, temporarily shut down some cvars and restore afterwards
5737         qualityreduction = r_water_lowquality.integer;
5738         if (qualityreduction > 0)
5739         {
5740                 if (qualityreduction >= 1)
5741                 {
5742                         old_r_shadows = r_shadows.integer;
5743                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5744                         old_r_dlight = r_shadow_realtime_dlight.integer;
5745                         Cvar_SetValueQuick(&r_shadows, 0);
5746                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5747                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5748                 }
5749                 if (qualityreduction >= 2)
5750                 {
5751                         old_r_dynamic = r_dynamic.integer;
5752                         old_r_particles = r_drawparticles.integer;
5753                         old_r_decals = r_drawdecals.integer;
5754                         Cvar_SetValueQuick(&r_dynamic, 0);
5755                         Cvar_SetValueQuick(&r_drawparticles, 0);
5756                         Cvar_SetValueQuick(&r_drawdecals, 0);
5757                 }
5758         }
5759
5760         // make sure enough textures are allocated
5761         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5762         {
5763                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5764                 {
5765                         if (!p->texture_refraction)
5766                                 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);
5767                         if (!p->texture_refraction)
5768                                 goto error;
5769                         if (usewaterfbo)
5770                         {
5771                                 if (r_fb.water.depthtexture == NULL)
5772                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5773                                 if (p->fbo_refraction == 0)
5774                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5775                         }
5776                 }
5777                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5778                 {
5779                         if (!p->texture_camera)
5780                                 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);
5781                         if (!p->texture_camera)
5782                                 goto error;
5783                         if (usewaterfbo)
5784                         {
5785                                 if (r_fb.water.depthtexture == NULL)
5786                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5787                                 if (p->fbo_camera == 0)
5788                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5789                         }
5790                 }
5791
5792                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5793                 {
5794                         if (!p->texture_reflection)
5795                                 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);
5796                         if (!p->texture_reflection)
5797                                 goto error;
5798                         if (usewaterfbo)
5799                         {
5800                                 if (r_fb.water.depthtexture == NULL)
5801                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5802                                 if (p->fbo_reflection == 0)
5803                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5804                         }
5805                 }
5806         }
5807
5808         // render views
5809         r_refdef.view = originalview;
5810         r_refdef.view.showdebug = false;
5811         r_refdef.view.width = r_fb.water.waterwidth;
5812         r_refdef.view.height = r_fb.water.waterheight;
5813         r_refdef.view.useclipplane = true;
5814         myview = r_refdef.view;
5815         r_fb.water.renderingscene = true;
5816         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5817         {
5818                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5819                 {
5820                         r_refdef.view = myview;
5821                         if(r_water_scissormode.integer)
5822                         {
5823                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5824                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5825                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5826                         }
5827
5828                         // render reflected scene and copy into texture
5829                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5830                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5831                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5832                         r_refdef.view.clipplane = p->plane;
5833                         // reverse the cullface settings for this render
5834                         r_refdef.view.cullface_front = GL_FRONT;
5835                         r_refdef.view.cullface_back = GL_BACK;
5836                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5837                         {
5838                                 r_refdef.view.usecustompvs = true;
5839                                 if (p->pvsvalid)
5840                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5841                                 else
5842                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5843                         }
5844
5845                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5846                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5847                         R_ClearScreen(r_refdef.fogenabled);
5848                         if(r_water_scissormode.integer & 2)
5849                                 R_View_UpdateWithScissor(myscissor);
5850                         else
5851                                 R_View_Update();
5852                         R_AnimCache_CacheVisibleEntities();
5853                         if(r_water_scissormode.integer & 1)
5854                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5855                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5856
5857                         if (!p->fbo_reflection)
5858                                 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);
5859                         r_fb.water.hideplayer = false;
5860                 }
5861
5862                 // render the normal view scene and copy into texture
5863                 // (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)
5864                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5865                 {
5866                         r_refdef.view = myview;
5867                         if(r_water_scissormode.integer)
5868                         {
5869                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5870                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5871                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5872                         }
5873
5874                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5875
5876                         r_refdef.view.clipplane = p->plane;
5877                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5878                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5879
5880                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5881                         {
5882                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5883                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5884                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5885                                 R_RenderView_UpdateViewVectors();
5886                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5887                                 {
5888                                         r_refdef.view.usecustompvs = true;
5889                                         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);
5890                                 }
5891                         }
5892
5893                         PlaneClassify(&r_refdef.view.clipplane);
5894
5895                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5896                         R_ClearScreen(r_refdef.fogenabled);
5897                         if(r_water_scissormode.integer & 2)
5898                                 R_View_UpdateWithScissor(myscissor);
5899                         else
5900                                 R_View_Update();
5901                         R_AnimCache_CacheVisibleEntities();
5902                         if(r_water_scissormode.integer & 1)
5903                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5904                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5905
5906                         if (!p->fbo_refraction)
5907                                 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);
5908                         r_fb.water.hideplayer = false;
5909                 }
5910                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5911                 {
5912                         r_refdef.view = myview;
5913
5914                         r_refdef.view.clipplane = p->plane;
5915                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5916                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5917
5918                         r_refdef.view.width = r_fb.water.camerawidth;
5919                         r_refdef.view.height = r_fb.water.cameraheight;
5920                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5921                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5922                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5923                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5924
5925                         if(p->camera_entity)
5926                         {
5927                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5928                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5929                         }
5930
5931                         // note: all of the view is used for displaying... so
5932                         // there is no use in scissoring
5933
5934                         // reverse the cullface settings for this render
5935                         r_refdef.view.cullface_front = GL_FRONT;
5936                         r_refdef.view.cullface_back = GL_BACK;
5937                         // also reverse the view matrix
5938                         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
5939                         R_RenderView_UpdateViewVectors();
5940                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5941                         {
5942                                 r_refdef.view.usecustompvs = true;
5943                                 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);
5944                         }
5945                         
5946                         // camera needs no clipplane
5947                         r_refdef.view.useclipplane = false;
5948
5949                         PlaneClassify(&r_refdef.view.clipplane);
5950
5951                         r_fb.water.hideplayer = false;
5952
5953                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5954                         R_ClearScreen(r_refdef.fogenabled);
5955                         R_View_Update();
5956                         R_AnimCache_CacheVisibleEntities();
5957                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5958
5959                         if (!p->fbo_camera)
5960                                 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);
5961                         r_fb.water.hideplayer = false;
5962                 }
5963
5964         }
5965         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5966         r_fb.water.renderingscene = false;
5967         r_refdef.view = originalview;
5968         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5969         if (!r_fb.water.depthtexture)
5970                 R_ClearScreen(r_refdef.fogenabled);
5971         R_View_Update();
5972         R_AnimCache_CacheVisibleEntities();
5973         goto finish;
5974 error:
5975         r_refdef.view = originalview;
5976         r_fb.water.renderingscene = false;
5977         Cvar_SetValueQuick(&r_water, 0);
5978         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5979 finish:
5980         // lowquality hack, restore cvars
5981         if (qualityreduction > 0)
5982         {
5983                 if (qualityreduction >= 1)
5984                 {
5985                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5986                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5987                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5988                 }
5989                 if (qualityreduction >= 2)
5990                 {
5991                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5992                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5993                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5994                 }
5995         }
5996 }
5997
5998 static void R_Bloom_StartFrame(void)
5999 {
6000         int i;
6001         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6002         int viewwidth, viewheight;
6003         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
6004         textype_t textype = TEXTYPE_COLORBUFFER;
6005
6006         switch (vid.renderpath)
6007         {
6008         case RENDERPATH_GL20:
6009                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6010                 if (vid.support.ext_framebuffer_object)
6011                 {
6012                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6013                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6014                 }
6015                 break;
6016         case RENDERPATH_GL11:
6017         case RENDERPATH_GL13:
6018         case RENDERPATH_GLES1:
6019         case RENDERPATH_GLES2:
6020         case RENDERPATH_D3D9:
6021         case RENDERPATH_D3D10:
6022         case RENDERPATH_D3D11:
6023                 r_fb.usedepthtextures = false;
6024                 break;
6025         case RENDERPATH_SOFT:
6026                 r_fb.usedepthtextures = true;
6027                 break;
6028         }
6029
6030         if (r_viewscale_fpsscaling.integer)
6031         {
6032                 double actualframetime;
6033                 double targetframetime;
6034                 double adjust;
6035                 actualframetime = r_refdef.lastdrawscreentime;
6036                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6037                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6038                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6039                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6040                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6041                 viewscalefpsadjusted += adjust;
6042                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6043         }
6044         else
6045                 viewscalefpsadjusted = 1.0f;
6046
6047         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6048
6049         switch(vid.renderpath)
6050         {
6051         case RENDERPATH_GL20:
6052         case RENDERPATH_D3D9:
6053         case RENDERPATH_D3D10:
6054         case RENDERPATH_D3D11:
6055         case RENDERPATH_SOFT:
6056         case RENDERPATH_GLES2:
6057                 break;
6058         case RENDERPATH_GL11:
6059         case RENDERPATH_GL13:
6060         case RENDERPATH_GLES1:
6061                 return;
6062         }
6063
6064         // set bloomwidth and bloomheight to the bloom resolution that will be
6065         // used (often less than the screen resolution for faster rendering)
6066         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6067         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6068         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6069         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6070         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6071
6072         // calculate desired texture sizes
6073         if (vid.support.arb_texture_non_power_of_two)
6074         {
6075                 screentexturewidth = vid.width;
6076                 screentextureheight = vid.height;
6077                 bloomtexturewidth = r_fb.bloomwidth;
6078                 bloomtextureheight = r_fb.bloomheight;
6079         }
6080         else
6081         {
6082                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6083                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6084                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6085                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6086         }
6087
6088         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))
6089         {
6090                 Cvar_SetValueQuick(&r_bloom, 0);
6091                 Cvar_SetValueQuick(&r_motionblur, 0);
6092                 Cvar_SetValueQuick(&r_damageblur, 0);
6093         }
6094
6095         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6096          && !r_bloom.integer
6097          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6098          && !useviewfbo
6099          && r_viewscale.value == 1.0f
6100          && !r_viewscale_fpsscaling.integer)
6101                 screentexturewidth = screentextureheight = 0;
6102         if (!r_bloom.integer)
6103                 bloomtexturewidth = bloomtextureheight = 0;
6104
6105         // allocate textures as needed
6106         if (r_fb.screentexturewidth != screentexturewidth
6107          || r_fb.screentextureheight != screentextureheight
6108          || r_fb.bloomtexturewidth != bloomtexturewidth
6109          || r_fb.bloomtextureheight != bloomtextureheight
6110          || r_fb.textype != textype
6111          || useviewfbo != (r_fb.fbo != 0))
6112         {
6113                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6114                 {
6115                         if (r_fb.bloomtexture[i])
6116                                 R_FreeTexture(r_fb.bloomtexture[i]);
6117                         r_fb.bloomtexture[i] = NULL;
6118
6119                         if (r_fb.bloomfbo[i])
6120                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6121                         r_fb.bloomfbo[i] = 0;
6122                 }
6123
6124                 if (r_fb.fbo)
6125                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6126                 r_fb.fbo = 0;
6127
6128                 if (r_fb.colortexture)
6129                         R_FreeTexture(r_fb.colortexture);
6130                 r_fb.colortexture = NULL;
6131
6132                 if (r_fb.depthtexture)
6133                         R_FreeTexture(r_fb.depthtexture);
6134                 r_fb.depthtexture = NULL;
6135
6136                 if (r_fb.ghosttexture)
6137                         R_FreeTexture(r_fb.ghosttexture);
6138                 r_fb.ghosttexture = NULL;
6139
6140                 r_fb.screentexturewidth = screentexturewidth;
6141                 r_fb.screentextureheight = screentextureheight;
6142                 r_fb.bloomtexturewidth = bloomtexturewidth;
6143                 r_fb.bloomtextureheight = bloomtextureheight;
6144                 r_fb.textype = textype;
6145
6146                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6147                 {
6148                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6149                                 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);
6150                         r_fb.ghosttexture_valid = false;
6151                         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);
6152                         if (useviewfbo)
6153                         {
6154                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6155                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6156                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6157                         }
6158                 }
6159
6160                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6161                 {
6162                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6163                         {
6164                                 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);
6165                                 if (useviewfbo)
6166                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6167                         }
6168                 }
6169         }
6170
6171         // bloom texture is a different resolution
6172         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6173         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6174         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6175         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6176         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6177
6178         // set up a texcoord array for the full resolution screen image
6179         // (we have to keep this around to copy back during final render)
6180         r_fb.screentexcoord2f[0] = 0;
6181         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6182         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6183         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6184         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6185         r_fb.screentexcoord2f[5] = 0;
6186         r_fb.screentexcoord2f[6] = 0;
6187         r_fb.screentexcoord2f[7] = 0;
6188
6189         if(r_fb.fbo) 
6190         {
6191                 for (i = 1;i < 8;i += 2)
6192                 {
6193                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6194                 }
6195         }
6196
6197         // set up a texcoord array for the reduced resolution bloom image
6198         // (which will be additive blended over the screen image)
6199         r_fb.bloomtexcoord2f[0] = 0;
6200         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6201         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6202         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6203         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6204         r_fb.bloomtexcoord2f[5] = 0;
6205         r_fb.bloomtexcoord2f[6] = 0;
6206         r_fb.bloomtexcoord2f[7] = 0;
6207
6208         switch(vid.renderpath)
6209         {
6210         case RENDERPATH_GL11:
6211         case RENDERPATH_GL13:
6212         case RENDERPATH_GL20:
6213         case RENDERPATH_SOFT:
6214         case RENDERPATH_GLES1:
6215         case RENDERPATH_GLES2:
6216                 break;
6217         case RENDERPATH_D3D9:
6218         case RENDERPATH_D3D10:
6219         case RENDERPATH_D3D11:
6220                 for (i = 0;i < 4;i++)
6221                 {
6222                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6223                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6224                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6225                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6226                 }
6227                 break;
6228         }
6229
6230         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6231
6232         if (r_fb.fbo)
6233                 r_refdef.view.clear = true;
6234 }
6235
6236 static void R_Bloom_MakeTexture(void)
6237 {
6238         int x, range, dir;
6239         float xoffset, yoffset, r, brighten;
6240         rtexture_t *intex;
6241         float colorscale = r_bloom_colorscale.value;
6242
6243         r_refdef.stats.bloom++;
6244     
6245 #if 0
6246     // this copy is unnecessary since it happens in R_BlendView already
6247         if (!r_fb.fbo)
6248         {
6249                 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);
6250                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6251         }
6252 #endif
6253
6254         // scale down screen texture to the bloom texture size
6255         CHECKGLERROR
6256         r_fb.bloomindex = 0;
6257         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6258         R_SetViewport(&r_fb.bloomviewport);
6259         GL_DepthTest(false);
6260         GL_BlendFunc(GL_ONE, GL_ZERO);
6261         GL_Color(colorscale, colorscale, colorscale, 1);
6262         // 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...
6263         switch(vid.renderpath)
6264         {
6265         case RENDERPATH_GL11:
6266         case RENDERPATH_GL13:
6267         case RENDERPATH_GL20:
6268         case RENDERPATH_GLES1:
6269         case RENDERPATH_GLES2:
6270         case RENDERPATH_SOFT:
6271                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6272                 break;
6273         case RENDERPATH_D3D9:
6274         case RENDERPATH_D3D10:
6275         case RENDERPATH_D3D11:
6276                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6277                 break;
6278         }
6279         // TODO: do boxfilter scale-down in shader?
6280         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6281         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6282         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6283
6284         // we now have a properly scaled bloom image
6285         if (!r_fb.bloomfbo[r_fb.bloomindex])
6286         {
6287                 // copy it into the bloom texture
6288                 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);
6289                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6290         }
6291
6292         // multiply bloom image by itself as many times as desired
6293         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6294         {
6295                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6296                 r_fb.bloomindex ^= 1;
6297                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6298                 x *= 2;
6299                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6300                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6301                 {
6302                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6303                         GL_Color(r,r,r,1); // apply fix factor
6304                 }
6305                 else
6306                 {
6307                         if(x <= 2)
6308                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6309                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6310                         GL_Color(1,1,1,1); // no fix factor supported here
6311                 }
6312                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6313                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6314                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6315                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6316
6317                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6318                 {
6319                         // copy the darkened image to a texture
6320                         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);
6321                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6322                 }
6323         }
6324
6325         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6326         brighten = r_bloom_brighten.value;
6327         brighten = sqrt(brighten);
6328         if(range >= 1)
6329                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6330
6331         for (dir = 0;dir < 2;dir++)
6332         {
6333                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6334                 r_fb.bloomindex ^= 1;
6335                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6336                 // blend on at multiple vertical offsets to achieve a vertical blur
6337                 // TODO: do offset blends using GLSL
6338                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6339                 GL_BlendFunc(GL_ONE, GL_ZERO);
6340                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6341                 for (x = -range;x <= range;x++)
6342                 {
6343                         if (!dir){xoffset = 0;yoffset = x;}
6344                         else {xoffset = x;yoffset = 0;}
6345                         xoffset /= (float)r_fb.bloomtexturewidth;
6346                         yoffset /= (float)r_fb.bloomtextureheight;
6347                         // compute a texcoord array with the specified x and y offset
6348                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6349                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6350                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6351                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6352                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6353                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6354                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6355                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6356                         // this r value looks like a 'dot' particle, fading sharply to
6357                         // black at the edges
6358                         // (probably not realistic but looks good enough)
6359                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6360                         //r = brighten/(range*2+1);
6361                         r = brighten / (range * 2 + 1);
6362                         if(range >= 1)
6363                                 r *= (1 - x*x/(float)(range*range));
6364                         GL_Color(r, r, r, 1);
6365                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6366                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6367                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6368                         GL_BlendFunc(GL_ONE, GL_ONE);
6369                 }
6370
6371                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6372                 {
6373                         // copy the vertically or horizontally blurred bloom view to a texture
6374                         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);
6375                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6376                 }
6377         }
6378 }
6379
6380 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6381 {
6382         unsigned int permutation;
6383         float uservecs[4][4];
6384
6385         R_EntityMatrix(&identitymatrix);
6386
6387         switch (vid.renderpath)
6388         {
6389         case RENDERPATH_GL20:
6390         case RENDERPATH_D3D9:
6391         case RENDERPATH_D3D10:
6392         case RENDERPATH_D3D11:
6393         case RENDERPATH_SOFT:
6394         case RENDERPATH_GLES2:
6395                 permutation =
6396                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6397                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6398                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6399                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6400                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6401
6402                 if (r_fb.colortexture)
6403                 {
6404                         if (!r_fb.fbo)
6405                         {
6406                                 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);
6407                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6408                         }
6409
6410                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6411                         {
6412                                 // declare variables
6413                                 float blur_factor, blur_mouseaccel, blur_velocity;
6414                                 static float blur_average; 
6415                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6416
6417                                 // set a goal for the factoring
6418                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6419                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6420                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6421                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6422                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6423                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6424
6425                                 // from the goal, pick an averaged value between goal and last value
6426                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6427                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6428
6429                                 // enforce minimum amount of blur 
6430                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6431
6432                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6433
6434                                 // calculate values into a standard alpha
6435                                 cl.motionbluralpha = 1 - exp(-
6436                                                 (
6437                                                  (r_motionblur.value * blur_factor / 80)
6438                                                  +
6439                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6440                                                 )
6441                                                 /
6442                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6443                                           );
6444
6445                                 // randomization for the blur value to combat persistent ghosting
6446                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6447                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6448
6449                                 // apply the blur
6450                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6451                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6452                                 {
6453                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6454                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6455                                         switch(vid.renderpath)
6456                                         {
6457                                         case RENDERPATH_GL11:
6458                                         case RENDERPATH_GL13:
6459                                         case RENDERPATH_GL20:
6460                                         case RENDERPATH_GLES1:
6461                                         case RENDERPATH_GLES2:
6462                                         case RENDERPATH_SOFT:
6463                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6464                                                 break;
6465                                         case RENDERPATH_D3D9:
6466                                         case RENDERPATH_D3D10:
6467                                         case RENDERPATH_D3D11:
6468                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6469                                                 break;
6470                                         }
6471                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6472                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6473                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6474                                 }
6475
6476                                 // updates old view angles for next pass
6477                                 VectorCopy(cl.viewangles, blur_oldangles);
6478
6479                                 // copy view into the ghost texture
6480                                 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);
6481                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6482                                 r_fb.ghosttexture_valid = true;
6483                         }
6484                 }
6485                 else
6486                 {
6487                         // no r_fb.colortexture means we're rendering to the real fb
6488                         // we may still have to do view tint...
6489                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6490                         {
6491                                 // apply a color tint to the whole view
6492                                 R_ResetViewRendering2D(0, NULL, NULL);
6493                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6494                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6495                                 R_SetupShader_Generic_NoTexture(false, true);
6496                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6497                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6498                         }
6499                         break; // no screen processing, no bloom, skip it
6500                 }
6501
6502                 if (r_fb.bloomtexture[0])
6503                 {
6504                         // make the bloom texture
6505                         R_Bloom_MakeTexture();
6506                 }
6507
6508 #if _MSC_VER >= 1400
6509 #define sscanf sscanf_s
6510 #endif
6511                 memset(uservecs, 0, sizeof(uservecs));
6512                 if (r_glsl_postprocess_uservec1_enable.integer)
6513                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6514                 if (r_glsl_postprocess_uservec2_enable.integer)
6515                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6516                 if (r_glsl_postprocess_uservec3_enable.integer)
6517                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6518                 if (r_glsl_postprocess_uservec4_enable.integer)
6519                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6520
6521                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6522                 GL_Color(1, 1, 1, 1);
6523                 GL_BlendFunc(GL_ONE, GL_ZERO);
6524
6525                 switch(vid.renderpath)
6526                 {
6527                 case RENDERPATH_GL20:
6528                 case RENDERPATH_GLES2:
6529                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6530                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6531                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6532                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6533                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6534                         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]);
6535                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6536                         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]);
6537                         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]);
6538                         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]);
6539                         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]);
6540                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6541                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6542                         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);
6543                         break;
6544                 case RENDERPATH_D3D9:
6545 #ifdef SUPPORTD3D
6546                         // 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...
6547                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6548                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6549                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6550                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6551                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6552                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6553                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6554                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6555                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6556                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6557                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6558                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6559                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6560                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6561 #endif
6562                         break;
6563                 case RENDERPATH_D3D10:
6564                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6565                         break;
6566                 case RENDERPATH_D3D11:
6567                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6568                         break;
6569                 case RENDERPATH_SOFT:
6570                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6571                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6572                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6573                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6574                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6575                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6576                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6577                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6578                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6579                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6580                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6581                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6582                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6583                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6584                         break;
6585                 default:
6586                         break;
6587                 }
6588                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6589                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6590                 break;
6591         case RENDERPATH_GL11:
6592         case RENDERPATH_GL13:
6593         case RENDERPATH_GLES1:
6594                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6595                 {
6596                         // apply a color tint to the whole view
6597                         R_ResetViewRendering2D(0, NULL, NULL);
6598                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6599                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6600                         R_SetupShader_Generic_NoTexture(false, true);
6601                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6602                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6603                 }
6604                 break;
6605         }
6606 }
6607
6608 matrix4x4_t r_waterscrollmatrix;
6609
6610 void R_UpdateFog(void)
6611 {
6612         // Nehahra fog
6613         if (gamemode == GAME_NEHAHRA)
6614         {
6615                 if (gl_fogenable.integer)
6616                 {
6617                         r_refdef.oldgl_fogenable = true;
6618                         r_refdef.fog_density = gl_fogdensity.value;
6619                         r_refdef.fog_red = gl_fogred.value;
6620                         r_refdef.fog_green = gl_foggreen.value;
6621                         r_refdef.fog_blue = gl_fogblue.value;
6622                         r_refdef.fog_alpha = 1;
6623                         r_refdef.fog_start = 0;
6624                         r_refdef.fog_end = gl_skyclip.value;
6625                         r_refdef.fog_height = 1<<30;
6626                         r_refdef.fog_fadedepth = 128;
6627                 }
6628                 else if (r_refdef.oldgl_fogenable)
6629                 {
6630                         r_refdef.oldgl_fogenable = false;
6631                         r_refdef.fog_density = 0;
6632                         r_refdef.fog_red = 0;
6633                         r_refdef.fog_green = 0;
6634                         r_refdef.fog_blue = 0;
6635                         r_refdef.fog_alpha = 0;
6636                         r_refdef.fog_start = 0;
6637                         r_refdef.fog_end = 0;
6638                         r_refdef.fog_height = 1<<30;
6639                         r_refdef.fog_fadedepth = 128;
6640                 }
6641         }
6642
6643         // fog parms
6644         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6645         r_refdef.fog_start = max(0, r_refdef.fog_start);
6646         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6647
6648         if (r_refdef.fog_density && r_drawfog.integer)
6649         {
6650                 r_refdef.fogenabled = true;
6651                 // this is the point where the fog reaches 0.9986 alpha, which we
6652                 // consider a good enough cutoff point for the texture
6653                 // (0.9986 * 256 == 255.6)
6654                 if (r_fog_exp2.integer)
6655                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6656                 else
6657                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6658                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6659                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6660                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6661                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6662                         R_BuildFogHeightTexture();
6663                 // fog color was already set
6664                 // update the fog texture
6665                 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)
6666                         R_BuildFogTexture();
6667                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6668                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6669         }
6670         else
6671                 r_refdef.fogenabled = false;
6672
6673         // fog color
6674         if (r_refdef.fog_density)
6675         {
6676                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6677                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6678                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6679
6680                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6681                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6682                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6683                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6684
6685                 {
6686                         vec3_t fogvec;
6687                         VectorCopy(r_refdef.fogcolor, fogvec);
6688                         //   color.rgb *= ContrastBoost * SceneBrightness;
6689                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6690                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6691                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6692                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6693                 }
6694         }
6695 }
6696
6697 void R_UpdateVariables(void)
6698 {
6699         R_Textures_Frame();
6700
6701         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6702
6703         r_refdef.farclip = r_farclip_base.value;
6704         if (r_refdef.scene.worldmodel)
6705                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6706         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6707
6708         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6709                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6710         r_refdef.polygonfactor = 0;
6711         r_refdef.polygonoffset = 0;
6712         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6713         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6714
6715         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6716         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6717         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6718         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6719         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6720         if (FAKELIGHT_ENABLED)
6721         {
6722                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6723         }
6724         else if (r_refdef.scene.worldmodel)
6725         {
6726                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6727         }
6728         if (r_showsurfaces.integer)
6729         {
6730                 r_refdef.scene.rtworld = false;
6731                 r_refdef.scene.rtworldshadows = false;
6732                 r_refdef.scene.rtdlight = false;
6733                 r_refdef.scene.rtdlightshadows = false;
6734                 r_refdef.lightmapintensity = 0;
6735         }
6736
6737         switch(vid.renderpath)
6738         {
6739         case RENDERPATH_GL20:
6740         case RENDERPATH_D3D9:
6741         case RENDERPATH_D3D10:
6742         case RENDERPATH_D3D11:
6743         case RENDERPATH_SOFT:
6744         case RENDERPATH_GLES2:
6745                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6746                 {
6747                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6748                         {
6749                                 // build GLSL gamma texture
6750 #define RAMPWIDTH 256
6751                                 unsigned short ramp[RAMPWIDTH * 3];
6752                                 unsigned char rampbgr[RAMPWIDTH][4];
6753                                 int i;
6754
6755                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6756
6757                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6758                                 for(i = 0; i < RAMPWIDTH; ++i)
6759                                 {
6760                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6761                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6762                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6763                                         rampbgr[i][3] = 0;
6764                                 }
6765                                 if (r_texture_gammaramps)
6766                                 {
6767                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6768                                 }
6769                                 else
6770                                 {
6771                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6772                                 }
6773                         }
6774                 }
6775                 else
6776                 {
6777                         // remove GLSL gamma texture
6778                 }
6779                 break;
6780         case RENDERPATH_GL11:
6781         case RENDERPATH_GL13:
6782         case RENDERPATH_GLES1:
6783                 break;
6784         }
6785 }
6786
6787 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6788 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6789 /*
6790 ================
6791 R_SelectScene
6792 ================
6793 */
6794 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6795         if( scenetype != r_currentscenetype ) {
6796                 // store the old scenetype
6797                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6798                 r_currentscenetype = scenetype;
6799                 // move in the new scene
6800                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6801         }
6802 }
6803
6804 /*
6805 ================
6806 R_GetScenePointer
6807 ================
6808 */
6809 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6810 {
6811         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6812         if( scenetype == r_currentscenetype ) {
6813                 return &r_refdef.scene;
6814         } else {
6815                 return &r_scenes_store[ scenetype ];
6816         }
6817 }
6818
6819 static int R_SortEntities_Compare(const void *ap, const void *bp)
6820 {
6821         const entity_render_t *a = *(const entity_render_t **)ap;
6822         const entity_render_t *b = *(const entity_render_t **)bp;
6823
6824         // 1. compare model
6825         if(a->model < b->model)
6826                 return -1;
6827         if(a->model > b->model)
6828                 return +1;
6829
6830         // 2. compare skin
6831         // TODO possibly calculate the REAL skinnum here first using
6832         // skinscenes?
6833         if(a->skinnum < b->skinnum)
6834                 return -1;
6835         if(a->skinnum > b->skinnum)
6836                 return +1;
6837
6838         // everything we compared is equal
6839         return 0;
6840 }
6841 static void R_SortEntities(void)
6842 {
6843         // below or equal 2 ents, sorting never gains anything
6844         if(r_refdef.scene.numentities <= 2)
6845                 return;
6846         // sort
6847         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6848 }
6849
6850 /*
6851 ================
6852 R_RenderView
6853 ================
6854 */
6855 int dpsoftrast_test;
6856 extern cvar_t r_shadow_bouncegrid;
6857 void R_RenderView(void)
6858 {
6859         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6860         int fbo;
6861         rtexture_t *depthtexture;
6862         rtexture_t *colortexture;
6863
6864         dpsoftrast_test = r_test.integer;
6865
6866         if (r_timereport_active)
6867                 R_TimeReport("start");
6868         r_textureframe++; // used only by R_GetCurrentTexture
6869         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6870
6871         if(R_CompileShader_CheckStaticParms())
6872                 R_GLSL_Restart_f();
6873
6874         if (!r_drawentities.integer)
6875                 r_refdef.scene.numentities = 0;
6876         else if (r_sortentities.integer)
6877                 R_SortEntities();
6878
6879         R_AnimCache_ClearCache();
6880         R_FrameData_NewFrame();
6881
6882         /* adjust for stereo display */
6883         if(R_Stereo_Active())
6884         {
6885                 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);
6886                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6887         }
6888
6889         if (r_refdef.view.isoverlay)
6890         {
6891                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6892                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6893                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6894                 R_TimeReport("depthclear");
6895
6896                 r_refdef.view.showdebug = false;
6897
6898                 r_fb.water.enabled = false;
6899                 r_fb.water.numwaterplanes = 0;
6900
6901                 R_RenderScene(0, NULL, NULL);
6902
6903                 r_refdef.view.matrix = originalmatrix;
6904
6905                 CHECKGLERROR
6906                 return;
6907         }
6908
6909         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6910         {
6911                 r_refdef.view.matrix = originalmatrix;
6912                 return;
6913         }
6914
6915         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6916
6917         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6918                 // in sRGB fallback, behave similar to true sRGB: convert this
6919                 // value from linear to sRGB
6920                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6921
6922         R_RenderView_UpdateViewVectors();
6923
6924         R_Shadow_UpdateWorldLightSelection();
6925
6926         R_Bloom_StartFrame();
6927
6928         // apply bloom brightness offset
6929         if(r_fb.bloomtexture[0])
6930                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
6931
6932         R_Water_StartFrame();
6933
6934         // now we probably have an fbo to render into
6935         fbo = r_fb.fbo;
6936         depthtexture = r_fb.depthtexture;
6937         colortexture = r_fb.colortexture;
6938
6939         CHECKGLERROR
6940         if (r_timereport_active)
6941                 R_TimeReport("viewsetup");
6942
6943         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6944
6945         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6946         {
6947                 R_ClearScreen(r_refdef.fogenabled);
6948                 if (r_timereport_active)
6949                         R_TimeReport("viewclear");
6950         }
6951         r_refdef.view.clear = true;
6952
6953         r_refdef.view.showdebug = true;
6954
6955         R_View_Update();
6956         if (r_timereport_active)
6957                 R_TimeReport("visibility");
6958
6959         R_AnimCache_CacheVisibleEntities();
6960         if (r_timereport_active)
6961                 R_TimeReport("animcache");
6962
6963         R_Shadow_UpdateBounceGridTexture();
6964         if (r_timereport_active && r_shadow_bouncegrid.integer)
6965                 R_TimeReport("bouncegrid");
6966
6967         r_fb.water.numwaterplanes = 0;
6968         if (r_fb.water.enabled)
6969                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6970
6971         R_RenderScene(fbo, depthtexture, colortexture);
6972         r_fb.water.numwaterplanes = 0;
6973
6974         R_BlendView(fbo, depthtexture, colortexture);
6975         if (r_timereport_active)
6976                 R_TimeReport("blendview");
6977
6978         GL_Scissor(0, 0, vid.width, vid.height);
6979         GL_ScissorTest(false);
6980
6981         r_refdef.view.matrix = originalmatrix;
6982
6983         CHECKGLERROR
6984 }
6985
6986 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6987 {
6988         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6989         {
6990                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6991                 if (r_timereport_active)
6992                         R_TimeReport("waterworld");
6993         }
6994
6995         // don't let sound skip if going slow
6996         if (r_refdef.scene.extraupdate)
6997                 S_ExtraUpdate ();
6998
6999         R_DrawModelsAddWaterPlanes();
7000         if (r_timereport_active)
7001                 R_TimeReport("watermodels");
7002
7003         if (r_fb.water.numwaterplanes)
7004         {
7005                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7006                 if (r_timereport_active)
7007                         R_TimeReport("waterscenes");
7008         }
7009 }
7010
7011 extern cvar_t cl_locs_show;
7012 static void R_DrawLocs(void);
7013 static void R_DrawEntityBBoxes(void);
7014 static void R_DrawModelDecals(void);
7015 extern cvar_t cl_decals_newsystem;
7016 extern qboolean r_shadow_usingdeferredprepass;
7017 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7018 {
7019         qboolean shadowmapping = false;
7020
7021         if (r_timereport_active)
7022                 R_TimeReport("beginscene");
7023
7024         r_refdef.stats.renders++;
7025
7026         R_UpdateFog();
7027
7028         // don't let sound skip if going slow
7029         if (r_refdef.scene.extraupdate)
7030                 S_ExtraUpdate ();
7031
7032         R_MeshQueue_BeginScene();
7033
7034         R_SkyStartFrame();
7035
7036         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);
7037
7038         if (r_timereport_active)
7039                 R_TimeReport("skystartframe");
7040
7041         if (cl.csqc_vidvars.drawworld)
7042         {
7043                 // don't let sound skip if going slow
7044                 if (r_refdef.scene.extraupdate)
7045                         S_ExtraUpdate ();
7046
7047                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7048                 {
7049                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7050                         if (r_timereport_active)
7051                                 R_TimeReport("worldsky");
7052                 }
7053
7054                 if (R_DrawBrushModelsSky() && r_timereport_active)
7055                         R_TimeReport("bmodelsky");
7056
7057                 if (skyrendermasked && skyrenderlater)
7058                 {
7059                         // we have to force off the water clipping plane while rendering sky
7060                         R_SetupView(false, fbo, depthtexture, colortexture);
7061                         R_Sky();
7062                         R_SetupView(true, fbo, depthtexture, colortexture);
7063                         if (r_timereport_active)
7064                                 R_TimeReport("sky");
7065                 }
7066         }
7067
7068         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7069         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7070                 R_Shadow_PrepareModelShadows();
7071         if (r_timereport_active)
7072                 R_TimeReport("preparelights");
7073
7074         if (R_Shadow_ShadowMappingEnabled())
7075                 shadowmapping = true;
7076
7077         if (r_shadow_usingdeferredprepass)
7078                 R_Shadow_DrawPrepass();
7079
7080         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7081         {
7082                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7083                 if (r_timereport_active)
7084                         R_TimeReport("worlddepth");
7085         }
7086         if (r_depthfirst.integer >= 2)
7087         {
7088                 R_DrawModelsDepth();
7089                 if (r_timereport_active)
7090                         R_TimeReport("modeldepth");
7091         }
7092
7093         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7094         {
7095                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7096                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7097                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7098                 // don't let sound skip if going slow
7099                 if (r_refdef.scene.extraupdate)
7100                         S_ExtraUpdate ();
7101         }
7102
7103         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7104         {
7105                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7106                 if (r_timereport_active)
7107                         R_TimeReport("world");
7108         }
7109
7110         // don't let sound skip if going slow
7111         if (r_refdef.scene.extraupdate)
7112                 S_ExtraUpdate ();
7113
7114         R_DrawModels();
7115         if (r_timereport_active)
7116                 R_TimeReport("models");
7117
7118         // don't let sound skip if going slow
7119         if (r_refdef.scene.extraupdate)
7120                 S_ExtraUpdate ();
7121
7122         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7123         {
7124                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7125                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7126                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7127                 // don't let sound skip if going slow
7128                 if (r_refdef.scene.extraupdate)
7129                         S_ExtraUpdate ();
7130         }
7131
7132         if (!r_shadow_usingdeferredprepass)
7133         {
7134                 R_Shadow_DrawLights();
7135                 if (r_timereport_active)
7136                         R_TimeReport("rtlights");
7137         }
7138
7139         // don't let sound skip if going slow
7140         if (r_refdef.scene.extraupdate)
7141                 S_ExtraUpdate ();
7142
7143         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7144         {
7145                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7146                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7147                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7148                 // don't let sound skip if going slow
7149                 if (r_refdef.scene.extraupdate)
7150                         S_ExtraUpdate ();
7151         }
7152
7153         if (cl.csqc_vidvars.drawworld)
7154         {
7155                 if (cl_decals_newsystem.integer)
7156                 {
7157                         R_DrawModelDecals();
7158                         if (r_timereport_active)
7159                                 R_TimeReport("modeldecals");
7160                 }
7161                 else
7162                 {
7163                         R_DrawDecals();
7164                         if (r_timereport_active)
7165                                 R_TimeReport("decals");
7166                 }
7167
7168                 R_DrawParticles();
7169                 if (r_timereport_active)
7170                         R_TimeReport("particles");
7171
7172                 R_DrawExplosions();
7173                 if (r_timereport_active)
7174                         R_TimeReport("explosions");
7175
7176                 R_DrawLightningBeams();
7177                 if (r_timereport_active)
7178                         R_TimeReport("lightning");
7179         }
7180
7181         if (cl.csqc_loaded)
7182                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7183
7184         if (r_refdef.view.showdebug)
7185         {
7186                 if (cl_locs_show.integer)
7187                 {
7188                         R_DrawLocs();
7189                         if (r_timereport_active)
7190                                 R_TimeReport("showlocs");
7191                 }
7192
7193                 if (r_drawportals.integer)
7194                 {
7195                         R_DrawPortals();
7196                         if (r_timereport_active)
7197                                 R_TimeReport("portals");
7198                 }
7199
7200                 if (r_showbboxes.value > 0)
7201                 {
7202                         R_DrawEntityBBoxes();
7203                         if (r_timereport_active)
7204                                 R_TimeReport("bboxes");
7205                 }
7206         }
7207
7208         if (r_transparent.integer)
7209         {
7210                 R_MeshQueue_RenderTransparent();
7211                 if (r_timereport_active)
7212                         R_TimeReport("drawtrans");
7213         }
7214
7215         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))
7216         {
7217                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7218                 if (r_timereport_active)
7219                         R_TimeReport("worlddebug");
7220                 R_DrawModelsDebug();
7221                 if (r_timereport_active)
7222                         R_TimeReport("modeldebug");
7223         }
7224
7225         if (cl.csqc_vidvars.drawworld)
7226         {
7227                 R_Shadow_DrawCoronas();
7228                 if (r_timereport_active)
7229                         R_TimeReport("coronas");
7230         }
7231
7232 #if 0
7233         {
7234                 GL_DepthTest(false);
7235                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7236                 GL_Color(1, 1, 1, 1);
7237                 qglBegin(GL_POLYGON);
7238                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7239                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7240                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7241                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7242                 qglEnd();
7243                 qglBegin(GL_POLYGON);
7244                 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]);
7245                 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]);
7246                 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]);
7247                 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]);
7248                 qglEnd();
7249                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7250         }
7251 #endif
7252
7253         // don't let sound skip if going slow
7254         if (r_refdef.scene.extraupdate)
7255                 S_ExtraUpdate ();
7256 }
7257
7258 static const unsigned short bboxelements[36] =
7259 {
7260         5, 1, 3, 5, 3, 7,
7261         6, 2, 0, 6, 0, 4,
7262         7, 3, 2, 7, 2, 6,
7263         4, 0, 1, 4, 1, 5,
7264         4, 5, 7, 4, 7, 6,
7265         1, 0, 2, 1, 2, 3,
7266 };
7267
7268 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7269 {
7270         int i;
7271         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7272
7273         RSurf_ActiveWorldEntity();
7274
7275         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7276         GL_DepthMask(false);
7277         GL_DepthRange(0, 1);
7278         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7279 //      R_Mesh_ResetTextureState();
7280
7281         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7282         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7283         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7284         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7285         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7286         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7287         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7288         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7289         R_FillColors(color4f, 8, cr, cg, cb, ca);
7290         if (r_refdef.fogenabled)
7291         {
7292                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7293                 {
7294                         f1 = RSurf_FogVertex(v);
7295                         f2 = 1 - f1;
7296                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7297                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7298                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7299                 }
7300         }
7301         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7302         R_Mesh_ResetTextureState();
7303         R_SetupShader_Generic_NoTexture(false, false);
7304         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7305 }
7306
7307 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7308 {
7309         prvm_prog_t *prog = SVVM_prog;
7310         int i;
7311         float color[4];
7312         prvm_edict_t *edict;
7313
7314         // this function draws bounding boxes of server entities
7315         if (!sv.active)
7316                 return;
7317
7318         GL_CullFace(GL_NONE);
7319         R_SetupShader_Generic_NoTexture(false, false);
7320
7321         for (i = 0;i < numsurfaces;i++)
7322         {
7323                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7324                 switch ((int)PRVM_serveredictfloat(edict, solid))
7325                 {
7326                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7327                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7328                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7329                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7330                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7331                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7332                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7333                 }
7334                 color[3] *= r_showbboxes.value;
7335                 color[3] = bound(0, color[3], 1);
7336                 GL_DepthTest(!r_showdisabledepthtest.integer);
7337                 GL_CullFace(r_refdef.view.cullface_front);
7338                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7339         }
7340 }
7341
7342 static void R_DrawEntityBBoxes(void)
7343 {
7344         int i;
7345         prvm_edict_t *edict;
7346         vec3_t center;
7347         prvm_prog_t *prog = SVVM_prog;
7348
7349         // this function draws bounding boxes of server entities
7350         if (!sv.active)
7351                 return;
7352
7353         for (i = 0;i < prog->num_edicts;i++)
7354         {
7355                 edict = PRVM_EDICT_NUM(i);
7356                 if (edict->priv.server->free)
7357                         continue;
7358                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7359                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7360                         continue;
7361                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7362                         continue;
7363                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7364                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7365         }
7366 }
7367
7368 static const int nomodelelement3i[24] =
7369 {
7370         5, 2, 0,
7371         5, 1, 2,
7372         5, 0, 3,
7373         5, 3, 1,
7374         0, 2, 4,
7375         2, 1, 4,
7376         3, 0, 4,
7377         1, 3, 4
7378 };
7379
7380 static const unsigned short nomodelelement3s[24] =
7381 {
7382         5, 2, 0,
7383         5, 1, 2,
7384         5, 0, 3,
7385         5, 3, 1,
7386         0, 2, 4,
7387         2, 1, 4,
7388         3, 0, 4,
7389         1, 3, 4
7390 };
7391
7392 static const float nomodelvertex3f[6*3] =
7393 {
7394         -16,   0,   0,
7395          16,   0,   0,
7396           0, -16,   0,
7397           0,  16,   0,
7398           0,   0, -16,
7399           0,   0,  16
7400 };
7401
7402 static const float nomodelcolor4f[6*4] =
7403 {
7404         0.0f, 0.0f, 0.5f, 1.0f,
7405         0.0f, 0.0f, 0.5f, 1.0f,
7406         0.0f, 0.5f, 0.0f, 1.0f,
7407         0.0f, 0.5f, 0.0f, 1.0f,
7408         0.5f, 0.0f, 0.0f, 1.0f,
7409         0.5f, 0.0f, 0.0f, 1.0f
7410 };
7411
7412 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7413 {
7414         int i;
7415         float f1, f2, *c;
7416         float color4f[6*4];
7417
7418         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);
7419
7420         // this is only called once per entity so numsurfaces is always 1, and
7421         // surfacelist is always {0}, so this code does not handle batches
7422
7423         if (rsurface.ent_flags & RENDER_ADDITIVE)
7424         {
7425                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7426                 GL_DepthMask(false);
7427         }
7428         else if (rsurface.colormod[3] < 1)
7429         {
7430                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7431                 GL_DepthMask(false);
7432         }
7433         else
7434         {
7435                 GL_BlendFunc(GL_ONE, GL_ZERO);
7436                 GL_DepthMask(true);
7437         }
7438         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7439         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7440         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7441         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7442         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7443         for (i = 0, c = color4f;i < 6;i++, c += 4)
7444         {
7445                 c[0] *= rsurface.colormod[0];
7446                 c[1] *= rsurface.colormod[1];
7447                 c[2] *= rsurface.colormod[2];
7448                 c[3] *= rsurface.colormod[3];
7449         }
7450         if (r_refdef.fogenabled)
7451         {
7452                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7453                 {
7454                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7455                         f2 = 1 - f1;
7456                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7457                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7458                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7459                 }
7460         }
7461 //      R_Mesh_ResetTextureState();
7462         R_SetupShader_Generic_NoTexture(false, false);
7463         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7464         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7465 }
7466
7467 void R_DrawNoModel(entity_render_t *ent)
7468 {
7469         vec3_t org;
7470         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7471         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7472                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7473         else
7474                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7475 }
7476
7477 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7478 {
7479         vec3_t right1, right2, diff, normal;
7480
7481         VectorSubtract (org2, org1, normal);
7482
7483         // calculate 'right' vector for start
7484         VectorSubtract (r_refdef.view.origin, org1, diff);
7485         CrossProduct (normal, diff, right1);
7486         VectorNormalize (right1);
7487
7488         // calculate 'right' vector for end
7489         VectorSubtract (r_refdef.view.origin, org2, diff);
7490         CrossProduct (normal, diff, right2);
7491         VectorNormalize (right2);
7492
7493         vert[ 0] = org1[0] + width * right1[0];
7494         vert[ 1] = org1[1] + width * right1[1];
7495         vert[ 2] = org1[2] + width * right1[2];
7496         vert[ 3] = org1[0] - width * right1[0];
7497         vert[ 4] = org1[1] - width * right1[1];
7498         vert[ 5] = org1[2] - width * right1[2];
7499         vert[ 6] = org2[0] - width * right2[0];
7500         vert[ 7] = org2[1] - width * right2[1];
7501         vert[ 8] = org2[2] - width * right2[2];
7502         vert[ 9] = org2[0] + width * right2[0];
7503         vert[10] = org2[1] + width * right2[1];
7504         vert[11] = org2[2] + width * right2[2];
7505 }
7506
7507 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)
7508 {
7509         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7510         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7511         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7512         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7513         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7514         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7515         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7516         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7517         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7518         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7519         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7520         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7521 }
7522
7523 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7524 {
7525         int i;
7526         float *vertex3f;
7527         float v[3];
7528         VectorSet(v, x, y, z);
7529         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7530                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7531                         break;
7532         if (i == mesh->numvertices)
7533         {
7534                 if (mesh->numvertices < mesh->maxvertices)
7535                 {
7536                         VectorCopy(v, vertex3f);
7537                         mesh->numvertices++;
7538                 }
7539                 return mesh->numvertices;
7540         }
7541         else
7542                 return i;
7543 }
7544
7545 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7546 {
7547         int i;
7548         int *e, element[3];
7549         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7550         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7551         e = mesh->element3i + mesh->numtriangles * 3;
7552         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7553         {
7554                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7555                 if (mesh->numtriangles < mesh->maxtriangles)
7556                 {
7557                         *e++ = element[0];
7558                         *e++ = element[1];
7559                         *e++ = element[2];
7560                         mesh->numtriangles++;
7561                 }
7562                 element[1] = element[2];
7563         }
7564 }
7565
7566 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7567 {
7568         int i;
7569         int *e, element[3];
7570         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7571         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7572         e = mesh->element3i + mesh->numtriangles * 3;
7573         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7574         {
7575                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7576                 if (mesh->numtriangles < mesh->maxtriangles)
7577                 {
7578                         *e++ = element[0];
7579                         *e++ = element[1];
7580                         *e++ = element[2];
7581                         mesh->numtriangles++;
7582                 }
7583                 element[1] = element[2];
7584         }
7585 }
7586
7587 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7588 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7589 {
7590         int planenum, planenum2;
7591         int w;
7592         int tempnumpoints;
7593         mplane_t *plane, *plane2;
7594         double maxdist;
7595         double temppoints[2][256*3];
7596         // figure out how large a bounding box we need to properly compute this brush
7597         maxdist = 0;
7598         for (w = 0;w < numplanes;w++)
7599                 maxdist = max(maxdist, fabs(planes[w].dist));
7600         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7601         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7602         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7603         {
7604                 w = 0;
7605                 tempnumpoints = 4;
7606                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7607                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7608                 {
7609                         if (planenum2 == planenum)
7610                                 continue;
7611                         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);
7612                         w = !w;
7613                 }
7614                 if (tempnumpoints < 3)
7615                         continue;
7616                 // generate elements forming a triangle fan for this polygon
7617                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7618         }
7619 }
7620
7621 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)
7622 {
7623         texturelayer_t *layer;
7624         layer = t->currentlayers + t->currentnumlayers++;
7625         layer->type = type;
7626         layer->depthmask = depthmask;
7627         layer->blendfunc1 = blendfunc1;
7628         layer->blendfunc2 = blendfunc2;
7629         layer->texture = texture;
7630         layer->texmatrix = *matrix;
7631         layer->color[0] = r;
7632         layer->color[1] = g;
7633         layer->color[2] = b;
7634         layer->color[3] = a;
7635 }
7636
7637 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7638 {
7639         if(parms[0] == 0 && parms[1] == 0)
7640                 return false;
7641         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7642                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7643                         return false;
7644         return true;
7645 }
7646
7647 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7648 {
7649         double index, f;
7650         index = parms[2] + rsurface.shadertime * parms[3];
7651         index -= floor(index);
7652         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7653         {
7654         default:
7655         case Q3WAVEFUNC_NONE:
7656         case Q3WAVEFUNC_NOISE:
7657         case Q3WAVEFUNC_COUNT:
7658                 f = 0;
7659                 break;
7660         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7661         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7662         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7663         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7664         case Q3WAVEFUNC_TRIANGLE:
7665                 index *= 4;
7666                 f = index - floor(index);
7667                 if (index < 1)
7668                 {
7669                         // f = f;
7670                 }
7671                 else if (index < 2)
7672                         f = 1 - f;
7673                 else if (index < 3)
7674                         f = -f;
7675                 else
7676                         f = -(1 - f);
7677                 break;
7678         }
7679         f = parms[0] + parms[1] * f;
7680         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7681                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7682         return (float) f;
7683 }
7684
7685 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7686 {
7687         int w, h, idx;
7688         double f;
7689         double offsetd[2];
7690         float tcmat[12];
7691         matrix4x4_t matrix, temp;
7692         switch(tcmod->tcmod)
7693         {
7694                 case Q3TCMOD_COUNT:
7695                 case Q3TCMOD_NONE:
7696                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7697                                 matrix = r_waterscrollmatrix;
7698                         else
7699                                 matrix = identitymatrix;
7700                         break;
7701                 case Q3TCMOD_ENTITYTRANSLATE:
7702                         // this is used in Q3 to allow the gamecode to control texcoord
7703                         // scrolling on the entity, which is not supported in darkplaces yet.
7704                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7705                         break;
7706                 case Q3TCMOD_ROTATE:
7707                         f = tcmod->parms[0] * rsurface.shadertime;
7708                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7709                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7710                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7711                         break;
7712                 case Q3TCMOD_SCALE:
7713                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7714                         break;
7715                 case Q3TCMOD_SCROLL:
7716                         // extra care is needed because of precision breakdown with large values of time
7717                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7718                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7719                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7720                         break;
7721                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7722                         w = (int) tcmod->parms[0];
7723                         h = (int) tcmod->parms[1];
7724                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7725                         f = f - floor(f);
7726                         idx = (int) floor(f * w * h);
7727                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7728                         break;
7729                 case Q3TCMOD_STRETCH:
7730                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7731                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7732                         break;
7733                 case Q3TCMOD_TRANSFORM:
7734                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7735                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7736                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7737                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7738                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7739                         break;
7740                 case Q3TCMOD_TURBULENT:
7741                         // this is handled in the RSurf_PrepareVertices function
7742                         matrix = identitymatrix;
7743                         break;
7744         }
7745         temp = *texmatrix;
7746         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7747 }
7748
7749 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7750 {
7751         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7752         char name[MAX_QPATH];
7753         skinframe_t *skinframe;
7754         unsigned char pixels[296*194];
7755         strlcpy(cache->name, skinname, sizeof(cache->name));
7756         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7757         if (developer_loading.integer)
7758                 Con_Printf("loading %s\n", name);
7759         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7760         if (!skinframe || !skinframe->base)
7761         {
7762                 unsigned char *f;
7763                 fs_offset_t filesize;
7764                 skinframe = NULL;
7765                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7766                 if (f)
7767                 {
7768                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7769                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7770                         Mem_Free(f);
7771                 }
7772         }
7773         cache->skinframe = skinframe;
7774 }
7775
7776 texture_t *R_GetCurrentTexture(texture_t *t)
7777 {
7778         int i;
7779         const entity_render_t *ent = rsurface.entity;
7780         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7781         q3shaderinfo_layer_tcmod_t *tcmod;
7782
7783         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7784                 return t->currentframe;
7785         t->update_lastrenderframe = r_textureframe;
7786         t->update_lastrenderentity = (void *)ent;
7787
7788         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7789                 t->camera_entity = ent->entitynumber;
7790         else
7791                 t->camera_entity = 0;
7792
7793         // switch to an alternate material if this is a q1bsp animated material
7794         {
7795                 texture_t *texture = t;
7796                 int s = rsurface.ent_skinnum;
7797                 if ((unsigned int)s >= (unsigned int)model->numskins)
7798                         s = 0;
7799                 if (model->skinscenes)
7800                 {
7801                         if (model->skinscenes[s].framecount > 1)
7802                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7803                         else
7804                                 s = model->skinscenes[s].firstframe;
7805                 }
7806                 if (s > 0)
7807                         t = t + s * model->num_surfaces;
7808                 if (t->animated)
7809                 {
7810                         // use an alternate animation if the entity's frame is not 0,
7811                         // and only if the texture has an alternate animation
7812                         if (rsurface.ent_alttextures && t->anim_total[1])
7813                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7814                         else
7815                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7816                 }
7817                 texture->currentframe = t;
7818         }
7819
7820         // update currentskinframe to be a qw skin or animation frame
7821         if (rsurface.ent_qwskin >= 0)
7822         {
7823                 i = rsurface.ent_qwskin;
7824                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7825                 {
7826                         r_qwskincache_size = cl.maxclients;
7827                         if (r_qwskincache)
7828                                 Mem_Free(r_qwskincache);
7829                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7830                 }
7831                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7832                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7833                 t->currentskinframe = r_qwskincache[i].skinframe;
7834                 if (t->currentskinframe == NULL)
7835                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7836         }
7837         else if (t->numskinframes >= 2)
7838                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7839         if (t->backgroundnumskinframes >= 2)
7840                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7841
7842         t->currentmaterialflags = t->basematerialflags;
7843         t->currentalpha = rsurface.colormod[3];
7844         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7845                 t->currentalpha *= r_wateralpha.value;
7846         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7847                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7848         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7849                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7850         if (!(rsurface.ent_flags & RENDER_LIGHT))
7851                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7852         else if (FAKELIGHT_ENABLED)
7853         {
7854                 // no modellight if using fakelight for the map
7855         }
7856         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7857         {
7858                 // pick a model lighting mode
7859                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7860                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7861                 else
7862                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7863         }
7864         if (rsurface.ent_flags & RENDER_ADDITIVE)
7865                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7866         else if (t->currentalpha < 1)
7867                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7868         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7869         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7870                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7871         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7872                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7873         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7874                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7875         if (t->backgroundnumskinframes)
7876                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7877         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7878         {
7879                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7880                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7881         }
7882         else
7883                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7884         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7885         {
7886                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7887                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7888         }
7889         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7890                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7891
7892         // there is no tcmod
7893         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7894         {
7895                 t->currenttexmatrix = r_waterscrollmatrix;
7896                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7897         }
7898         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7899         {
7900                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7901                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7902         }
7903
7904         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7905                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7906         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7907                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7908
7909         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7910         if (t->currentskinframe->qpixels)
7911                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7912         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7913         if (!t->basetexture)
7914                 t->basetexture = r_texture_notexture;
7915         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7916         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7917         t->nmaptexture = t->currentskinframe->nmap;
7918         if (!t->nmaptexture)
7919                 t->nmaptexture = r_texture_blanknormalmap;
7920         t->glosstexture = r_texture_black;
7921         t->glowtexture = t->currentskinframe->glow;
7922         t->fogtexture = t->currentskinframe->fog;
7923         t->reflectmasktexture = t->currentskinframe->reflect;
7924         if (t->backgroundnumskinframes)
7925         {
7926                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7927                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7928                 t->backgroundglosstexture = r_texture_black;
7929                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7930                 if (!t->backgroundnmaptexture)
7931                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7932                 // make sure that if glow is going to be used, both textures are not NULL
7933                 if (!t->backgroundglowtexture && t->glowtexture)
7934                         t->backgroundglowtexture = r_texture_black;
7935                 if (!t->glowtexture && t->backgroundglowtexture)
7936                         t->glowtexture = r_texture_black;
7937         }
7938         else
7939         {
7940                 t->backgroundbasetexture = r_texture_white;
7941                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7942                 t->backgroundglosstexture = r_texture_black;
7943                 t->backgroundglowtexture = NULL;
7944         }
7945         t->specularpower = r_shadow_glossexponent.value;
7946         // TODO: store reference values for these in the texture?
7947         t->specularscale = 0;
7948         if (r_shadow_gloss.integer > 0)
7949         {
7950                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7951                 {
7952                         if (r_shadow_glossintensity.value > 0)
7953                         {
7954                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7955                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7956                                 t->specularscale = r_shadow_glossintensity.value;
7957                         }
7958                 }
7959                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7960                 {
7961                         t->glosstexture = r_texture_white;
7962                         t->backgroundglosstexture = r_texture_white;
7963                         t->specularscale = r_shadow_gloss2intensity.value;
7964                         t->specularpower = r_shadow_gloss2exponent.value;
7965                 }
7966         }
7967         t->specularscale *= t->specularscalemod;
7968         t->specularpower *= t->specularpowermod;
7969         t->rtlightambient = 0;
7970
7971         // lightmaps mode looks bad with dlights using actual texturing, so turn
7972         // off the colormap and glossmap, but leave the normalmap on as it still
7973         // accurately represents the shading involved
7974         if (gl_lightmaps.integer)
7975         {
7976                 t->basetexture = r_texture_grey128;
7977                 t->pantstexture = r_texture_black;
7978                 t->shirttexture = r_texture_black;
7979                 if (gl_lightmaps.integer < 2)
7980                         t->nmaptexture = r_texture_blanknormalmap;
7981                 t->glosstexture = r_texture_black;
7982                 t->glowtexture = NULL;
7983                 t->fogtexture = NULL;
7984                 t->reflectmasktexture = NULL;
7985                 t->backgroundbasetexture = NULL;
7986                 if (gl_lightmaps.integer < 2)
7987                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7988                 t->backgroundglosstexture = r_texture_black;
7989                 t->backgroundglowtexture = NULL;
7990                 t->specularscale = 0;
7991                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7992         }
7993
7994         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7995         VectorClear(t->dlightcolor);
7996         t->currentnumlayers = 0;
7997         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7998         {
7999                 int blendfunc1, blendfunc2;
8000                 qboolean depthmask;
8001                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8002                 {
8003                         blendfunc1 = GL_SRC_ALPHA;
8004                         blendfunc2 = GL_ONE;
8005                 }
8006                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8007                 {
8008                         blendfunc1 = GL_SRC_ALPHA;
8009                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8010                 }
8011                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8012                 {
8013                         blendfunc1 = t->customblendfunc[0];
8014                         blendfunc2 = t->customblendfunc[1];
8015                 }
8016                 else
8017                 {
8018                         blendfunc1 = GL_ONE;
8019                         blendfunc2 = GL_ZERO;
8020                 }
8021                 // don't colormod evilblend textures
8022                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8023                         VectorSet(t->lightmapcolor, 1, 1, 1);
8024                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8025                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8026                 {
8027                         // fullbright is not affected by r_refdef.lightmapintensity
8028                         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]);
8029                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8030                                 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]);
8031                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8032                                 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]);
8033                 }
8034                 else
8035                 {
8036                         vec3_t ambientcolor;
8037                         float colorscale;
8038                         // set the color tint used for lights affecting this surface
8039                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8040                         colorscale = 2;
8041                         // q3bsp has no lightmap updates, so the lightstylevalue that
8042                         // would normally be baked into the lightmap must be
8043                         // applied to the color
8044                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8045                         if (model->type == mod_brushq3)
8046                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8047                         colorscale *= r_refdef.lightmapintensity;
8048                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8049                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8050                         // basic lit geometry
8051                         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]);
8052                         // add pants/shirt if needed
8053                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8054                                 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]);
8055                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8056                                 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]);
8057                         // now add ambient passes if needed
8058                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8059                         {
8060                                 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]);
8061                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8062                                         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]);
8063                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8064                                         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]);
8065                         }
8066                 }
8067                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8068                         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]);
8069                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8070                 {
8071                         // if this is opaque use alpha blend which will darken the earlier
8072                         // passes cheaply.
8073                         //
8074                         // if this is an alpha blended material, all the earlier passes
8075                         // were darkened by fog already, so we only need to add the fog
8076                         // color ontop through the fog mask texture
8077                         //
8078                         // if this is an additive blended material, all the earlier passes
8079                         // were darkened by fog already, and we should not add fog color
8080                         // (because the background was not darkened, there is no fog color
8081                         // that was lost behind it).
8082                         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]);
8083                 }
8084         }
8085
8086         return t->currentframe;
8087 }
8088
8089 rsurfacestate_t rsurface;
8090
8091 void RSurf_ActiveWorldEntity(void)
8092 {
8093         dp_model_t *model = r_refdef.scene.worldmodel;
8094         //if (rsurface.entity == r_refdef.scene.worldentity)
8095         //      return;
8096         rsurface.entity = r_refdef.scene.worldentity;
8097         rsurface.skeleton = NULL;
8098         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8099         rsurface.ent_skinnum = 0;
8100         rsurface.ent_qwskin = -1;
8101         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8102         rsurface.shadertime = r_refdef.scene.time;
8103         rsurface.matrix = identitymatrix;
8104         rsurface.inversematrix = identitymatrix;
8105         rsurface.matrixscale = 1;
8106         rsurface.inversematrixscale = 1;
8107         R_EntityMatrix(&identitymatrix);
8108         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8109         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8110         rsurface.fograngerecip = r_refdef.fograngerecip;
8111         rsurface.fogheightfade = r_refdef.fogheightfade;
8112         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8113         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8114         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8115         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8116         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8117         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8118         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8119         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8120         rsurface.colormod[3] = 1;
8121         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);
8122         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8123         rsurface.frameblend[0].lerp = 1;
8124         rsurface.ent_alttextures = false;
8125         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8126         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8127         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8128         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8129         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8130         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8131         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8132         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8133         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8134         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8135         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8136         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8137         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8138         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8139         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8140         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8141         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8142         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8143         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8144         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8145         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8146         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8147         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8148         rsurface.modelelement3i = model->surfmesh.data_element3i;
8149         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8150         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8151         rsurface.modelelement3s = model->surfmesh.data_element3s;
8152         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8153         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8154         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8155         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8156         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8157         rsurface.modelsurfaces = model->data_surfaces;
8158         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8159         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8160         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8161         rsurface.modelgeneratedvertex = false;
8162         rsurface.batchgeneratedvertex = false;
8163         rsurface.batchfirstvertex = 0;
8164         rsurface.batchnumvertices = 0;
8165         rsurface.batchfirsttriangle = 0;
8166         rsurface.batchnumtriangles = 0;
8167         rsurface.batchvertex3f  = NULL;
8168         rsurface.batchvertex3f_vertexbuffer = NULL;
8169         rsurface.batchvertex3f_bufferoffset = 0;
8170         rsurface.batchsvector3f = NULL;
8171         rsurface.batchsvector3f_vertexbuffer = NULL;
8172         rsurface.batchsvector3f_bufferoffset = 0;
8173         rsurface.batchtvector3f = NULL;
8174         rsurface.batchtvector3f_vertexbuffer = NULL;
8175         rsurface.batchtvector3f_bufferoffset = 0;
8176         rsurface.batchnormal3f  = NULL;
8177         rsurface.batchnormal3f_vertexbuffer = NULL;
8178         rsurface.batchnormal3f_bufferoffset = 0;
8179         rsurface.batchlightmapcolor4f = NULL;
8180         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8181         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8182         rsurface.batchtexcoordtexture2f = NULL;
8183         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8184         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8185         rsurface.batchtexcoordlightmap2f = NULL;
8186         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8187         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8188         rsurface.batchvertexmesh = NULL;
8189         rsurface.batchvertexmeshbuffer = NULL;
8190         rsurface.batchvertex3fbuffer = NULL;
8191         rsurface.batchelement3i = NULL;
8192         rsurface.batchelement3i_indexbuffer = NULL;
8193         rsurface.batchelement3i_bufferoffset = 0;
8194         rsurface.batchelement3s = NULL;
8195         rsurface.batchelement3s_indexbuffer = NULL;
8196         rsurface.batchelement3s_bufferoffset = 0;
8197         rsurface.passcolor4f = NULL;
8198         rsurface.passcolor4f_vertexbuffer = NULL;
8199         rsurface.passcolor4f_bufferoffset = 0;
8200         rsurface.forcecurrenttextureupdate = false;
8201 }
8202
8203 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8204 {
8205         dp_model_t *model = ent->model;
8206         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8207         //      return;
8208         rsurface.entity = (entity_render_t *)ent;
8209         rsurface.skeleton = ent->skeleton;
8210         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8211         rsurface.ent_skinnum = ent->skinnum;
8212         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;
8213         rsurface.ent_flags = ent->flags;
8214         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8215         rsurface.matrix = ent->matrix;
8216         rsurface.inversematrix = ent->inversematrix;
8217         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8218         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8219         R_EntityMatrix(&rsurface.matrix);
8220         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8221         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8222         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8223         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8224         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8225         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8226         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8227         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8228         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8229         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8230         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8231         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8232         rsurface.colormod[3] = ent->alpha;
8233         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8234         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8235         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8236         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8237         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8238         if (ent->model->brush.submodel && !prepass)
8239         {
8240                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8241                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8242         }
8243         if (model->surfmesh.isanimated && model->AnimateVertices)
8244         {
8245                 if (ent->animcache_vertex3f)
8246                 {
8247                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8248                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8249                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8250                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8251                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8252                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8253                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8254                 }
8255                 else if (wanttangents)
8256                 {
8257                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8258                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8259                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8260                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8261                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8262                         rsurface.modelvertexmesh = NULL;
8263                         rsurface.modelvertexmeshbuffer = NULL;
8264                         rsurface.modelvertex3fbuffer = NULL;
8265                 }
8266                 else if (wantnormals)
8267                 {
8268                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8269                         rsurface.modelsvector3f = NULL;
8270                         rsurface.modeltvector3f = NULL;
8271                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8272                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8273                         rsurface.modelvertexmesh = NULL;
8274                         rsurface.modelvertexmeshbuffer = NULL;
8275                         rsurface.modelvertex3fbuffer = NULL;
8276                 }
8277                 else
8278                 {
8279                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8280                         rsurface.modelsvector3f = NULL;
8281                         rsurface.modeltvector3f = NULL;
8282                         rsurface.modelnormal3f = NULL;
8283                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8284                         rsurface.modelvertexmesh = NULL;
8285                         rsurface.modelvertexmeshbuffer = NULL;
8286                         rsurface.modelvertex3fbuffer = NULL;
8287                 }
8288                 rsurface.modelvertex3f_vertexbuffer = 0;
8289                 rsurface.modelvertex3f_bufferoffset = 0;
8290                 rsurface.modelsvector3f_vertexbuffer = 0;
8291                 rsurface.modelsvector3f_bufferoffset = 0;
8292                 rsurface.modeltvector3f_vertexbuffer = 0;
8293                 rsurface.modeltvector3f_bufferoffset = 0;
8294                 rsurface.modelnormal3f_vertexbuffer = 0;
8295                 rsurface.modelnormal3f_bufferoffset = 0;
8296                 rsurface.modelgeneratedvertex = true;
8297         }
8298         else
8299         {
8300                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8301                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8302                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8303                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8304                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8305                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8306                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8307                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8308                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8309                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8310                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8311                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8312                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8313                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8314                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8315                 rsurface.modelgeneratedvertex = false;
8316         }
8317         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8318         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8319         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8320         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8321         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8322         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8323         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8324         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8325         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8326         rsurface.modelelement3i = model->surfmesh.data_element3i;
8327         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8328         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8329         rsurface.modelelement3s = model->surfmesh.data_element3s;
8330         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8331         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8332         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8333         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8334         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8335         rsurface.modelsurfaces = model->data_surfaces;
8336         rsurface.batchgeneratedvertex = false;
8337         rsurface.batchfirstvertex = 0;
8338         rsurface.batchnumvertices = 0;
8339         rsurface.batchfirsttriangle = 0;
8340         rsurface.batchnumtriangles = 0;
8341         rsurface.batchvertex3f  = NULL;
8342         rsurface.batchvertex3f_vertexbuffer = NULL;
8343         rsurface.batchvertex3f_bufferoffset = 0;
8344         rsurface.batchsvector3f = NULL;
8345         rsurface.batchsvector3f_vertexbuffer = NULL;
8346         rsurface.batchsvector3f_bufferoffset = 0;
8347         rsurface.batchtvector3f = NULL;
8348         rsurface.batchtvector3f_vertexbuffer = NULL;
8349         rsurface.batchtvector3f_bufferoffset = 0;
8350         rsurface.batchnormal3f  = NULL;
8351         rsurface.batchnormal3f_vertexbuffer = NULL;
8352         rsurface.batchnormal3f_bufferoffset = 0;
8353         rsurface.batchlightmapcolor4f = NULL;
8354         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8355         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8356         rsurface.batchtexcoordtexture2f = NULL;
8357         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8358         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8359         rsurface.batchtexcoordlightmap2f = NULL;
8360         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8361         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8362         rsurface.batchvertexmesh = NULL;
8363         rsurface.batchvertexmeshbuffer = NULL;
8364         rsurface.batchvertex3fbuffer = NULL;
8365         rsurface.batchelement3i = NULL;
8366         rsurface.batchelement3i_indexbuffer = NULL;
8367         rsurface.batchelement3i_bufferoffset = 0;
8368         rsurface.batchelement3s = NULL;
8369         rsurface.batchelement3s_indexbuffer = NULL;
8370         rsurface.batchelement3s_bufferoffset = 0;
8371         rsurface.passcolor4f = NULL;
8372         rsurface.passcolor4f_vertexbuffer = NULL;
8373         rsurface.passcolor4f_bufferoffset = 0;
8374         rsurface.forcecurrenttextureupdate = false;
8375 }
8376
8377 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)
8378 {
8379         rsurface.entity = r_refdef.scene.worldentity;
8380         rsurface.skeleton = NULL;
8381         rsurface.ent_skinnum = 0;
8382         rsurface.ent_qwskin = -1;
8383         rsurface.ent_flags = entflags;
8384         rsurface.shadertime = r_refdef.scene.time - shadertime;
8385         rsurface.modelnumvertices = numvertices;
8386         rsurface.modelnumtriangles = numtriangles;
8387         rsurface.matrix = *matrix;
8388         rsurface.inversematrix = *inversematrix;
8389         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8390         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8391         R_EntityMatrix(&rsurface.matrix);
8392         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8393         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8394         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8395         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8396         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8397         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8398         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8399         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8400         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8401         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8402         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8403         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8404         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);
8405         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8406         rsurface.frameblend[0].lerp = 1;
8407         rsurface.ent_alttextures = false;
8408         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8409         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8410         if (wanttangents)
8411         {
8412                 rsurface.modelvertex3f = (float *)vertex3f;
8413                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8414                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8415                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8416         }
8417         else if (wantnormals)
8418         {
8419                 rsurface.modelvertex3f = (float *)vertex3f;
8420                 rsurface.modelsvector3f = NULL;
8421                 rsurface.modeltvector3f = NULL;
8422                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8423         }
8424         else
8425         {
8426                 rsurface.modelvertex3f = (float *)vertex3f;
8427                 rsurface.modelsvector3f = NULL;
8428                 rsurface.modeltvector3f = NULL;
8429                 rsurface.modelnormal3f = NULL;
8430         }
8431         rsurface.modelvertexmesh = NULL;
8432         rsurface.modelvertexmeshbuffer = NULL;
8433         rsurface.modelvertex3fbuffer = NULL;
8434         rsurface.modelvertex3f_vertexbuffer = 0;
8435         rsurface.modelvertex3f_bufferoffset = 0;
8436         rsurface.modelsvector3f_vertexbuffer = 0;
8437         rsurface.modelsvector3f_bufferoffset = 0;
8438         rsurface.modeltvector3f_vertexbuffer = 0;
8439         rsurface.modeltvector3f_bufferoffset = 0;
8440         rsurface.modelnormal3f_vertexbuffer = 0;
8441         rsurface.modelnormal3f_bufferoffset = 0;
8442         rsurface.modelgeneratedvertex = true;
8443         rsurface.modellightmapcolor4f  = (float *)color4f;
8444         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8445         rsurface.modellightmapcolor4f_bufferoffset = 0;
8446         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8447         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8448         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8449         rsurface.modeltexcoordlightmap2f  = NULL;
8450         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8451         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8452         rsurface.modelelement3i = (int *)element3i;
8453         rsurface.modelelement3i_indexbuffer = NULL;
8454         rsurface.modelelement3i_bufferoffset = 0;
8455         rsurface.modelelement3s = (unsigned short *)element3s;
8456         rsurface.modelelement3s_indexbuffer = NULL;
8457         rsurface.modelelement3s_bufferoffset = 0;
8458         rsurface.modellightmapoffsets = NULL;
8459         rsurface.modelsurfaces = NULL;
8460         rsurface.batchgeneratedvertex = false;
8461         rsurface.batchfirstvertex = 0;
8462         rsurface.batchnumvertices = 0;
8463         rsurface.batchfirsttriangle = 0;
8464         rsurface.batchnumtriangles = 0;
8465         rsurface.batchvertex3f  = NULL;
8466         rsurface.batchvertex3f_vertexbuffer = NULL;
8467         rsurface.batchvertex3f_bufferoffset = 0;
8468         rsurface.batchsvector3f = NULL;
8469         rsurface.batchsvector3f_vertexbuffer = NULL;
8470         rsurface.batchsvector3f_bufferoffset = 0;
8471         rsurface.batchtvector3f = NULL;
8472         rsurface.batchtvector3f_vertexbuffer = NULL;
8473         rsurface.batchtvector3f_bufferoffset = 0;
8474         rsurface.batchnormal3f  = NULL;
8475         rsurface.batchnormal3f_vertexbuffer = NULL;
8476         rsurface.batchnormal3f_bufferoffset = 0;
8477         rsurface.batchlightmapcolor4f = NULL;
8478         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8479         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8480         rsurface.batchtexcoordtexture2f = NULL;
8481         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8482         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8483         rsurface.batchtexcoordlightmap2f = NULL;
8484         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8485         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8486         rsurface.batchvertexmesh = NULL;
8487         rsurface.batchvertexmeshbuffer = NULL;
8488         rsurface.batchvertex3fbuffer = NULL;
8489         rsurface.batchelement3i = NULL;
8490         rsurface.batchelement3i_indexbuffer = NULL;
8491         rsurface.batchelement3i_bufferoffset = 0;
8492         rsurface.batchelement3s = NULL;
8493         rsurface.batchelement3s_indexbuffer = NULL;
8494         rsurface.batchelement3s_bufferoffset = 0;
8495         rsurface.passcolor4f = NULL;
8496         rsurface.passcolor4f_vertexbuffer = NULL;
8497         rsurface.passcolor4f_bufferoffset = 0;
8498         rsurface.forcecurrenttextureupdate = true;
8499
8500         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8501         {
8502                 if ((wantnormals || wanttangents) && !normal3f)
8503                 {
8504                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8505                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8506                 }
8507                 if (wanttangents && !svector3f)
8508                 {
8509                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8510                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8511                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8512                 }
8513         }
8514 }
8515
8516 float RSurf_FogPoint(const float *v)
8517 {
8518         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8519         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8520         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8521         float FogHeightFade = r_refdef.fogheightfade;
8522         float fogfrac;
8523         unsigned int fogmasktableindex;
8524         if (r_refdef.fogplaneviewabove)
8525                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8526         else
8527                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8528         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8529         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8530 }
8531
8532 float RSurf_FogVertex(const float *v)
8533 {
8534         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8535         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8536         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8537         float FogHeightFade = rsurface.fogheightfade;
8538         float fogfrac;
8539         unsigned int fogmasktableindex;
8540         if (r_refdef.fogplaneviewabove)
8541                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8542         else
8543                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8544         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8545         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8546 }
8547
8548 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8549 {
8550         int i;
8551         for (i = 0;i < numelements;i++)
8552                 outelement3i[i] = inelement3i[i] + adjust;
8553 }
8554
8555 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8556 extern cvar_t gl_vbo;
8557 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8558 {
8559         int deformindex;
8560         int firsttriangle;
8561         int numtriangles;
8562         int firstvertex;
8563         int endvertex;
8564         int numvertices;
8565         int surfacefirsttriangle;
8566         int surfacenumtriangles;
8567         int surfacefirstvertex;
8568         int surfaceendvertex;
8569         int surfacenumvertices;
8570         int batchnumvertices;
8571         int batchnumtriangles;
8572         int needsupdate;
8573         int i, j;
8574         qboolean gaps;
8575         qboolean dynamicvertex;
8576         float amplitude;
8577         float animpos;
8578         float scale;
8579         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8580         float waveparms[4];
8581         q3shaderinfo_deform_t *deform;
8582         const msurface_t *surface, *firstsurface;
8583         r_vertexmesh_t *vertexmesh;
8584         if (!texturenumsurfaces)
8585                 return;
8586         // find vertex range of this surface batch
8587         gaps = false;
8588         firstsurface = texturesurfacelist[0];
8589         firsttriangle = firstsurface->num_firsttriangle;
8590         batchnumvertices = 0;
8591         batchnumtriangles = 0;
8592         firstvertex = endvertex = firstsurface->num_firstvertex;
8593         for (i = 0;i < texturenumsurfaces;i++)
8594         {
8595                 surface = texturesurfacelist[i];
8596                 if (surface != firstsurface + i)
8597                         gaps = true;
8598                 surfacefirstvertex = surface->num_firstvertex;
8599                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8600                 surfacenumvertices = surface->num_vertices;
8601                 surfacenumtriangles = surface->num_triangles;
8602                 if (firstvertex > surfacefirstvertex)
8603                         firstvertex = surfacefirstvertex;
8604                 if (endvertex < surfaceendvertex)
8605                         endvertex = surfaceendvertex;
8606                 batchnumvertices += surfacenumvertices;
8607                 batchnumtriangles += surfacenumtriangles;
8608         }
8609
8610         // we now know the vertex range used, and if there are any gaps in it
8611         rsurface.batchfirstvertex = firstvertex;
8612         rsurface.batchnumvertices = endvertex - firstvertex;
8613         rsurface.batchfirsttriangle = firsttriangle;
8614         rsurface.batchnumtriangles = batchnumtriangles;
8615
8616         // this variable holds flags for which properties have been updated that
8617         // may require regenerating vertexmesh array...
8618         needsupdate = 0;
8619
8620         // check if any dynamic vertex processing must occur
8621         dynamicvertex = false;
8622
8623         // if there is a chance of animated vertex colors, it's a dynamic batch
8624         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8625         {
8626                 dynamicvertex = true;
8627                 batchneed |= BATCHNEED_NOGAPS;
8628                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8629         }
8630
8631         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8632         {
8633                 switch (deform->deform)
8634                 {
8635                 default:
8636                 case Q3DEFORM_PROJECTIONSHADOW:
8637                 case Q3DEFORM_TEXT0:
8638                 case Q3DEFORM_TEXT1:
8639                 case Q3DEFORM_TEXT2:
8640                 case Q3DEFORM_TEXT3:
8641                 case Q3DEFORM_TEXT4:
8642                 case Q3DEFORM_TEXT5:
8643                 case Q3DEFORM_TEXT6:
8644                 case Q3DEFORM_TEXT7:
8645                 case Q3DEFORM_NONE:
8646                         break;
8647                 case Q3DEFORM_AUTOSPRITE:
8648                         dynamicvertex = true;
8649                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8650                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8651                         break;
8652                 case Q3DEFORM_AUTOSPRITE2:
8653                         dynamicvertex = true;
8654                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8655                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8656                         break;
8657                 case Q3DEFORM_NORMAL:
8658                         dynamicvertex = true;
8659                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8660                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8661                         break;
8662                 case Q3DEFORM_WAVE:
8663                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8664                                 break; // if wavefunc is a nop, ignore this transform
8665                         dynamicvertex = true;
8666                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8667                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8668                         break;
8669                 case Q3DEFORM_BULGE:
8670                         dynamicvertex = true;
8671                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8672                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8673                         break;
8674                 case Q3DEFORM_MOVE:
8675                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8676                                 break; // if wavefunc is a nop, ignore this transform
8677                         dynamicvertex = true;
8678                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8679                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8680                         break;
8681                 }
8682         }
8683         switch(rsurface.texture->tcgen.tcgen)
8684         {
8685         default:
8686         case Q3TCGEN_TEXTURE:
8687                 break;
8688         case Q3TCGEN_LIGHTMAP:
8689                 dynamicvertex = true;
8690                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8691                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8692                 break;
8693         case Q3TCGEN_VECTOR:
8694                 dynamicvertex = true;
8695                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8696                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8697                 break;
8698         case Q3TCGEN_ENVIRONMENT:
8699                 dynamicvertex = true;
8700                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8701                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8702                 break;
8703         }
8704         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8705         {
8706                 dynamicvertex = true;
8707                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8708                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8709         }
8710
8711         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8712         {
8713                 dynamicvertex = true;
8714                 batchneed |= BATCHNEED_NOGAPS;
8715                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8716         }
8717
8718         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8719         {
8720                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8721                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8722                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8723                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8724                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8725                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8726                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8727         }
8728
8729         // when the model data has no vertex buffer (dynamic mesh), we need to
8730         // eliminate gaps
8731         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8732                 batchneed |= BATCHNEED_NOGAPS;
8733
8734         // if needsupdate, we have to do a dynamic vertex batch for sure
8735         if (needsupdate & batchneed)
8736                 dynamicvertex = true;
8737
8738         // see if we need to build vertexmesh from arrays
8739         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8740                 dynamicvertex = true;
8741
8742         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8743         // also some drivers strongly dislike firstvertex
8744         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8745                 dynamicvertex = true;
8746
8747         rsurface.batchvertex3f = rsurface.modelvertex3f;
8748         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8749         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8750         rsurface.batchsvector3f = rsurface.modelsvector3f;
8751         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8752         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8753         rsurface.batchtvector3f = rsurface.modeltvector3f;
8754         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8755         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8756         rsurface.batchnormal3f = rsurface.modelnormal3f;
8757         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8758         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8759         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8760         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8761         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8762         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8763         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8764         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8765         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8766         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8767         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8768         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8769         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8770         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8771         rsurface.batchelement3i = rsurface.modelelement3i;
8772         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8773         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8774         rsurface.batchelement3s = rsurface.modelelement3s;
8775         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8776         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8777
8778         // if any dynamic vertex processing has to occur in software, we copy the
8779         // entire surface list together before processing to rebase the vertices
8780         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8781         //
8782         // if any gaps exist and we do not have a static vertex buffer, we have to
8783         // copy the surface list together to avoid wasting upload bandwidth on the
8784         // vertices in the gaps.
8785         //
8786         // if gaps exist and we have a static vertex buffer, we still have to
8787         // combine the index buffer ranges into one dynamic index buffer.
8788         //
8789         // in all cases we end up with data that can be drawn in one call.
8790
8791         if (!dynamicvertex)
8792         {
8793                 // static vertex data, just set pointers...
8794                 rsurface.batchgeneratedvertex = false;
8795                 // if there are gaps, we want to build a combined index buffer,
8796                 // otherwise use the original static buffer with an appropriate offset
8797                 if (gaps)
8798                 {
8799                         // build a new triangle elements array for this batch
8800                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8801                         rsurface.batchfirsttriangle = 0;
8802                         numtriangles = 0;
8803                         for (i = 0;i < texturenumsurfaces;i++)
8804                         {
8805                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8806                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8807                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8808                                 numtriangles += surfacenumtriangles;
8809                         }
8810                         rsurface.batchelement3i_indexbuffer = NULL;
8811                         rsurface.batchelement3i_bufferoffset = 0;
8812                         rsurface.batchelement3s = NULL;
8813                         rsurface.batchelement3s_indexbuffer = NULL;
8814                         rsurface.batchelement3s_bufferoffset = 0;
8815                         if (endvertex <= 65536)
8816                         {
8817                                 // make a 16bit (unsigned short) index array if possible
8818                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8819                                 for (i = 0;i < numtriangles*3;i++)
8820                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8821                         }
8822                 }
8823                 return;
8824         }
8825
8826         // something needs software processing, do it for real...
8827         // we only directly handle separate array data in this case and then
8828         // generate interleaved data if needed...
8829         rsurface.batchgeneratedvertex = true;
8830
8831         // now copy the vertex data into a combined array and make an index array
8832         // (this is what Quake3 does all the time)
8833         //if (gaps || rsurface.batchfirstvertex)
8834         {
8835                 rsurface.batchvertex3fbuffer = NULL;
8836                 rsurface.batchvertexmesh = NULL;
8837                 rsurface.batchvertexmeshbuffer = NULL;
8838                 rsurface.batchvertex3f = NULL;
8839                 rsurface.batchvertex3f_vertexbuffer = NULL;
8840                 rsurface.batchvertex3f_bufferoffset = 0;
8841                 rsurface.batchsvector3f = NULL;
8842                 rsurface.batchsvector3f_vertexbuffer = NULL;
8843                 rsurface.batchsvector3f_bufferoffset = 0;
8844                 rsurface.batchtvector3f = NULL;
8845                 rsurface.batchtvector3f_vertexbuffer = NULL;
8846                 rsurface.batchtvector3f_bufferoffset = 0;
8847                 rsurface.batchnormal3f = NULL;
8848                 rsurface.batchnormal3f_vertexbuffer = NULL;
8849                 rsurface.batchnormal3f_bufferoffset = 0;
8850                 rsurface.batchlightmapcolor4f = NULL;
8851                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8852                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8853                 rsurface.batchtexcoordtexture2f = NULL;
8854                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8855                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8856                 rsurface.batchtexcoordlightmap2f = NULL;
8857                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8858                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8859                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8860                 rsurface.batchelement3i_indexbuffer = NULL;
8861                 rsurface.batchelement3i_bufferoffset = 0;
8862                 rsurface.batchelement3s = NULL;
8863                 rsurface.batchelement3s_indexbuffer = NULL;
8864                 rsurface.batchelement3s_bufferoffset = 0;
8865                 // we'll only be setting up certain arrays as needed
8866                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8867                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8868                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8869                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8870                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8871                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8872                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8873                 {
8874                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8875                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8876                 }
8877                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8878                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8879                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8880                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8881                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8882                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8883                 numvertices = 0;
8884                 numtriangles = 0;
8885                 for (i = 0;i < texturenumsurfaces;i++)
8886                 {
8887                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8888                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8889                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8890                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8891                         // copy only the data requested
8892                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8893                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8894                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8895                         {
8896                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8897                                 {
8898                                         if (rsurface.batchvertex3f)
8899                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8900                                         else
8901                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8902                                 }
8903                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8904                                 {
8905                                         if (rsurface.modelnormal3f)
8906                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8907                                         else
8908                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8909                                 }
8910                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8911                                 {
8912                                         if (rsurface.modelsvector3f)
8913                                         {
8914                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8915                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8916                                         }
8917                                         else
8918                                         {
8919                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8920                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8921                                         }
8922                                 }
8923                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8924                                 {
8925                                         if (rsurface.modellightmapcolor4f)
8926                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8927                                         else
8928                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8929                                 }
8930                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8931                                 {
8932                                         if (rsurface.modeltexcoordtexture2f)
8933                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8934                                         else
8935                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8936                                 }
8937                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8938                                 {
8939                                         if (rsurface.modeltexcoordlightmap2f)
8940                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8941                                         else
8942                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8943                                 }
8944                         }
8945                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8946                         numvertices += surfacenumvertices;
8947                         numtriangles += surfacenumtriangles;
8948                 }
8949
8950                 // generate a 16bit index array as well if possible
8951                 // (in general, dynamic batches fit)
8952                 if (numvertices <= 65536)
8953                 {
8954                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8955                         for (i = 0;i < numtriangles*3;i++)
8956                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8957                 }
8958
8959                 // since we've copied everything, the batch now starts at 0
8960                 rsurface.batchfirstvertex = 0;
8961                 rsurface.batchnumvertices = batchnumvertices;
8962                 rsurface.batchfirsttriangle = 0;
8963                 rsurface.batchnumtriangles = batchnumtriangles;
8964         }
8965
8966         // q1bsp surfaces rendered in vertex color mode have to have colors
8967         // calculated based on lightstyles
8968         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8969         {
8970                 // generate color arrays for the surfaces in this list
8971                 int c[4];
8972                 int scale;
8973                 int size3;
8974                 const int *offsets;
8975                 const unsigned char *lm;
8976                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8977                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8978                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8979                 numvertices = 0;
8980                 for (i = 0;i < texturenumsurfaces;i++)
8981                 {
8982                         surface = texturesurfacelist[i];
8983                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8984                         surfacenumvertices = surface->num_vertices;
8985                         if (surface->lightmapinfo->samples)
8986                         {
8987                                 for (j = 0;j < surfacenumvertices;j++)
8988                                 {
8989                                         lm = surface->lightmapinfo->samples + offsets[j];
8990                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8991                                         VectorScale(lm, scale, c);
8992                                         if (surface->lightmapinfo->styles[1] != 255)
8993                                         {
8994                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8995                                                 lm += size3;
8996                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8997                                                 VectorMA(c, scale, lm, c);
8998                                                 if (surface->lightmapinfo->styles[2] != 255)
8999                                                 {
9000                                                         lm += size3;
9001                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9002                                                         VectorMA(c, scale, lm, c);
9003                                                         if (surface->lightmapinfo->styles[3] != 255)
9004                                                         {
9005                                                                 lm += size3;
9006                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9007                                                                 VectorMA(c, scale, lm, c);
9008                                                         }
9009                                                 }
9010                                         }
9011                                         c[0] >>= 7;
9012                                         c[1] >>= 7;
9013                                         c[2] >>= 7;
9014                                         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);
9015                                         numvertices++;
9016                                 }
9017                         }
9018                         else
9019                         {
9020                                 for (j = 0;j < surfacenumvertices;j++)
9021                                 {
9022                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9023                                         numvertices++;
9024                                 }
9025                         }
9026                 }
9027         }
9028
9029         // if vertices are deformed (sprite flares and things in maps, possibly
9030         // water waves, bulges and other deformations), modify the copied vertices
9031         // in place
9032         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9033         {
9034                 switch (deform->deform)
9035                 {
9036                 default:
9037                 case Q3DEFORM_PROJECTIONSHADOW:
9038                 case Q3DEFORM_TEXT0:
9039                 case Q3DEFORM_TEXT1:
9040                 case Q3DEFORM_TEXT2:
9041                 case Q3DEFORM_TEXT3:
9042                 case Q3DEFORM_TEXT4:
9043                 case Q3DEFORM_TEXT5:
9044                 case Q3DEFORM_TEXT6:
9045                 case Q3DEFORM_TEXT7:
9046                 case Q3DEFORM_NONE:
9047                         break;
9048                 case Q3DEFORM_AUTOSPRITE:
9049                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9050                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9051                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9052                         VectorNormalize(newforward);
9053                         VectorNormalize(newright);
9054                         VectorNormalize(newup);
9055 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9056 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9057 //                      rsurface.batchvertex3f_bufferoffset = 0;
9058 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9059 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9060 //                      rsurface.batchsvector3f_bufferoffset = 0;
9061 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9062 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9063 //                      rsurface.batchtvector3f_bufferoffset = 0;
9064 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9065 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9066 //                      rsurface.batchnormal3f_bufferoffset = 0;
9067                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9068                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9069                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9070                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9071                                 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);
9072                         // a single autosprite surface can contain multiple sprites...
9073                         for (j = 0;j < batchnumvertices - 3;j += 4)
9074                         {
9075                                 VectorClear(center);
9076                                 for (i = 0;i < 4;i++)
9077                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9078                                 VectorScale(center, 0.25f, center);
9079                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9080                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9081                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9082                                 for (i = 0;i < 4;i++)
9083                                 {
9084                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9085                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9086                                 }
9087                         }
9088                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9089                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9090                         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);
9091                         break;
9092                 case Q3DEFORM_AUTOSPRITE2:
9093                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9094                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9095                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9096                         VectorNormalize(newforward);
9097                         VectorNormalize(newright);
9098                         VectorNormalize(newup);
9099 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9100 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9101 //                      rsurface.batchvertex3f_bufferoffset = 0;
9102                         {
9103                                 const float *v1, *v2;
9104                                 vec3_t start, end;
9105                                 float f, l;
9106                                 struct
9107                                 {
9108                                         float length2;
9109                                         const float *v1;
9110                                         const float *v2;
9111                                 }
9112                                 shortest[2];
9113                                 memset(shortest, 0, sizeof(shortest));
9114                                 // a single autosprite surface can contain multiple sprites...
9115                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9116                                 {
9117                                         VectorClear(center);
9118                                         for (i = 0;i < 4;i++)
9119                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9120                                         VectorScale(center, 0.25f, center);
9121                                         // find the two shortest edges, then use them to define the
9122                                         // axis vectors for rotating around the central axis
9123                                         for (i = 0;i < 6;i++)
9124                                         {
9125                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9126                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9127                                                 l = VectorDistance2(v1, v2);
9128                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9129                                                 if (v1[2] != v2[2])
9130                                                         l += (1.0f / 1024.0f);
9131                                                 if (shortest[0].length2 > l || i == 0)
9132                                                 {
9133                                                         shortest[1] = shortest[0];
9134                                                         shortest[0].length2 = l;
9135                                                         shortest[0].v1 = v1;
9136                                                         shortest[0].v2 = v2;
9137                                                 }
9138                                                 else if (shortest[1].length2 > l || i == 1)
9139                                                 {
9140                                                         shortest[1].length2 = l;
9141                                                         shortest[1].v1 = v1;
9142                                                         shortest[1].v2 = v2;
9143                                                 }
9144                                         }
9145                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9146                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9147                                         // this calculates the right vector from the shortest edge
9148                                         // and the up vector from the edge midpoints
9149                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9150                                         VectorNormalize(right);
9151                                         VectorSubtract(end, start, up);
9152                                         VectorNormalize(up);
9153                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9154                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9155                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9156                                         VectorNegate(forward, forward);
9157                                         VectorReflect(forward, 0, up, forward);
9158                                         VectorNormalize(forward);
9159                                         CrossProduct(up, forward, newright);
9160                                         VectorNormalize(newright);
9161                                         // rotate the quad around the up axis vector, this is made
9162                                         // especially easy by the fact we know the quad is flat,
9163                                         // so we only have to subtract the center position and
9164                                         // measure distance along the right vector, and then
9165                                         // multiply that by the newright vector and add back the
9166                                         // center position
9167                                         // we also need to subtract the old position to undo the
9168                                         // displacement from the center, which we do with a
9169                                         // DotProduct, the subtraction/addition of center is also
9170                                         // optimized into DotProducts here
9171                                         l = DotProduct(right, center);
9172                                         for (i = 0;i < 4;i++)
9173                                         {
9174                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9175                                                 f = DotProduct(right, v1) - l;
9176                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9177                                         }
9178                                 }
9179                         }
9180                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9181                         {
9182 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9183 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9184 //                              rsurface.batchnormal3f_bufferoffset = 0;
9185                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9186                         }
9187                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9188                         {
9189 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9190 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9191 //                              rsurface.batchsvector3f_bufferoffset = 0;
9192 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9193 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9194 //                              rsurface.batchtvector3f_bufferoffset = 0;
9195                                 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);
9196                         }
9197                         break;
9198                 case Q3DEFORM_NORMAL:
9199                         // deform the normals to make reflections wavey
9200                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9201                         rsurface.batchnormal3f_vertexbuffer = NULL;
9202                         rsurface.batchnormal3f_bufferoffset = 0;
9203                         for (j = 0;j < batchnumvertices;j++)
9204                         {
9205                                 float vertex[3];
9206                                 float *normal = rsurface.batchnormal3f + 3*j;
9207                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9208                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9209                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9210                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9211                                 VectorNormalize(normal);
9212                         }
9213                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9214                         {
9215 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9216 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9217 //                              rsurface.batchsvector3f_bufferoffset = 0;
9218 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9219 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9220 //                              rsurface.batchtvector3f_bufferoffset = 0;
9221                                 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);
9222                         }
9223                         break;
9224                 case Q3DEFORM_WAVE:
9225                         // deform vertex array to make wavey water and flags and such
9226                         waveparms[0] = deform->waveparms[0];
9227                         waveparms[1] = deform->waveparms[1];
9228                         waveparms[2] = deform->waveparms[2];
9229                         waveparms[3] = deform->waveparms[3];
9230                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9231                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9232                         // this is how a divisor of vertex influence on deformation
9233                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9234                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9235 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9236 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9237 //                      rsurface.batchvertex3f_bufferoffset = 0;
9238 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9239 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9240 //                      rsurface.batchnormal3f_bufferoffset = 0;
9241                         for (j = 0;j < batchnumvertices;j++)
9242                         {
9243                                 // if the wavefunc depends on time, evaluate it per-vertex
9244                                 if (waveparms[3])
9245                                 {
9246                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9247                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9248                                 }
9249                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9250                         }
9251                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9252                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9253                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9254                         {
9255 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9256 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9257 //                              rsurface.batchsvector3f_bufferoffset = 0;
9258 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9259 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9260 //                              rsurface.batchtvector3f_bufferoffset = 0;
9261                                 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);
9262                         }
9263                         break;
9264                 case Q3DEFORM_BULGE:
9265                         // deform vertex array to make the surface have moving bulges
9266 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9267 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9268 //                      rsurface.batchvertex3f_bufferoffset = 0;
9269 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9270 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9271 //                      rsurface.batchnormal3f_bufferoffset = 0;
9272                         for (j = 0;j < batchnumvertices;j++)
9273                         {
9274                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9275                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9276                         }
9277                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9278                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9279                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9280                         {
9281 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9282 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9283 //                              rsurface.batchsvector3f_bufferoffset = 0;
9284 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9285 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9286 //                              rsurface.batchtvector3f_bufferoffset = 0;
9287                                 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);
9288                         }
9289                         break;
9290                 case Q3DEFORM_MOVE:
9291                         // deform vertex array
9292                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9293                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9294                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9295                         VectorScale(deform->parms, scale, waveparms);
9296 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9297 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9298 //                      rsurface.batchvertex3f_bufferoffset = 0;
9299                         for (j = 0;j < batchnumvertices;j++)
9300                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9301                         break;
9302                 }
9303         }
9304
9305         // generate texcoords based on the chosen texcoord source
9306         switch(rsurface.texture->tcgen.tcgen)
9307         {
9308         default:
9309         case Q3TCGEN_TEXTURE:
9310                 break;
9311         case Q3TCGEN_LIGHTMAP:
9312 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9313 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9314 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9315                 if (rsurface.batchtexcoordlightmap2f)
9316                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9317                 break;
9318         case Q3TCGEN_VECTOR:
9319 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9320 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9321 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9322                 for (j = 0;j < batchnumvertices;j++)
9323                 {
9324                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9325                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9326                 }
9327                 break;
9328         case Q3TCGEN_ENVIRONMENT:
9329                 // make environment reflections using a spheremap
9330                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9331                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9332                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9333                 for (j = 0;j < batchnumvertices;j++)
9334                 {
9335                         // identical to Q3A's method, but executed in worldspace so
9336                         // carried models can be shiny too
9337
9338                         float viewer[3], d, reflected[3], worldreflected[3];
9339
9340                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9341                         // VectorNormalize(viewer);
9342
9343                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9344
9345                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9346                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9347                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9348                         // note: this is proportinal to viewer, so we can normalize later
9349
9350                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9351                         VectorNormalize(worldreflected);
9352
9353                         // note: this sphere map only uses world x and z!
9354                         // so positive and negative y will LOOK THE SAME.
9355                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9356                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9357                 }
9358                 break;
9359         }
9360         // the only tcmod that needs software vertex processing is turbulent, so
9361         // check for it here and apply the changes if needed
9362         // and we only support that as the first one
9363         // (handling a mixture of turbulent and other tcmods would be problematic
9364         //  without punting it entirely to a software path)
9365         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9366         {
9367                 amplitude = rsurface.texture->tcmods[0].parms[1];
9368                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9369 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9370 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9371 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9372                 for (j = 0;j < batchnumvertices;j++)
9373                 {
9374                         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);
9375                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9376                 }
9377         }
9378
9379         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9380         {
9381                 // convert the modified arrays to vertex structs
9382 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9383 //              rsurface.batchvertexmeshbuffer = NULL;
9384                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9385                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9386                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9387                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9388                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9389                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9390                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9391                 {
9392                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9393                         {
9394                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9395                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9396                         }
9397                 }
9398                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9399                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9400                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9401                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9402                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9403                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9404                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9405                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9406                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9407         }
9408 }
9409
9410 void RSurf_DrawBatch(void)
9411 {
9412         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9413         // through the pipeline, killing it earlier in the pipeline would have
9414         // per-surface overhead rather than per-batch overhead, so it's best to
9415         // reject it here, before it hits glDraw.
9416         if (rsurface.batchnumtriangles == 0)
9417                 return;
9418 #if 0
9419         // batch debugging code
9420         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9421         {
9422                 int i;
9423                 int j;
9424                 int c;
9425                 const int *e;
9426                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9427                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9428                 {
9429                         c = e[i];
9430                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9431                         {
9432                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9433                                 {
9434                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9435                                                 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);
9436                                         break;
9437                                 }
9438                         }
9439                 }
9440         }
9441 #endif
9442         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);
9443 }
9444
9445 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9446 {
9447         // pick the closest matching water plane
9448         int planeindex, vertexindex, bestplaneindex = -1;
9449         float d, bestd;
9450         vec3_t vert;
9451         const float *v;
9452         r_waterstate_waterplane_t *p;
9453         qboolean prepared = false;
9454         bestd = 0;
9455         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9456         {
9457                 if(p->camera_entity != rsurface.texture->camera_entity)
9458                         continue;
9459                 d = 0;
9460                 if(!prepared)
9461                 {
9462                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9463                         prepared = true;
9464                         if(rsurface.batchnumvertices == 0)
9465                                 break;
9466                 }
9467                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9468                 {
9469                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9470                         d += fabs(PlaneDiff(vert, &p->plane));
9471                 }
9472                 if (bestd > d || bestplaneindex < 0)
9473                 {
9474                         bestd = d;
9475                         bestplaneindex = planeindex;
9476                 }
9477         }
9478         return bestplaneindex;
9479         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9480         // this situation though, as it might be better to render single larger
9481         // batches with useless stuff (backface culled for example) than to
9482         // render multiple smaller batches
9483 }
9484
9485 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9486 {
9487         int i;
9488         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9489         rsurface.passcolor4f_vertexbuffer = 0;
9490         rsurface.passcolor4f_bufferoffset = 0;
9491         for (i = 0;i < rsurface.batchnumvertices;i++)
9492                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9493 }
9494
9495 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9496 {
9497         int i;
9498         float f;
9499         const float *v;
9500         const float *c;
9501         float *c2;
9502         if (rsurface.passcolor4f)
9503         {
9504                 // generate color arrays
9505                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9506                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9507                 rsurface.passcolor4f_vertexbuffer = 0;
9508                 rsurface.passcolor4f_bufferoffset = 0;
9509                 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)
9510                 {
9511                         f = RSurf_FogVertex(v);
9512                         c2[0] = c[0] * f;
9513                         c2[1] = c[1] * f;
9514                         c2[2] = c[2] * f;
9515                         c2[3] = c[3];
9516                 }
9517         }
9518         else
9519         {
9520                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9521                 rsurface.passcolor4f_vertexbuffer = 0;
9522                 rsurface.passcolor4f_bufferoffset = 0;
9523                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9524                 {
9525                         f = RSurf_FogVertex(v);
9526                         c2[0] = f;
9527                         c2[1] = f;
9528                         c2[2] = f;
9529                         c2[3] = 1;
9530                 }
9531         }
9532 }
9533
9534 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9535 {
9536         int i;
9537         float f;
9538         const float *v;
9539         const float *c;
9540         float *c2;
9541         if (!rsurface.passcolor4f)
9542                 return;
9543         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9544         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9545         rsurface.passcolor4f_vertexbuffer = 0;
9546         rsurface.passcolor4f_bufferoffset = 0;
9547         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)
9548         {
9549                 f = RSurf_FogVertex(v);
9550                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9551                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9552                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9553                 c2[3] = c[3];
9554         }
9555 }
9556
9557 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9558 {
9559         int i;
9560         const float *c;
9561         float *c2;
9562         if (!rsurface.passcolor4f)
9563                 return;
9564         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9565         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9566         rsurface.passcolor4f_vertexbuffer = 0;
9567         rsurface.passcolor4f_bufferoffset = 0;
9568         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9569         {
9570                 c2[0] = c[0] * r;
9571                 c2[1] = c[1] * g;
9572                 c2[2] = c[2] * b;
9573                 c2[3] = c[3] * a;
9574         }
9575 }
9576
9577 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9578 {
9579         int i;
9580         const float *c;
9581         float *c2;
9582         if (!rsurface.passcolor4f)
9583                 return;
9584         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9585         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9586         rsurface.passcolor4f_vertexbuffer = 0;
9587         rsurface.passcolor4f_bufferoffset = 0;
9588         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9589         {
9590                 c2[0] = c[0] + r_refdef.scene.ambient;
9591                 c2[1] = c[1] + r_refdef.scene.ambient;
9592                 c2[2] = c[2] + r_refdef.scene.ambient;
9593                 c2[3] = c[3];
9594         }
9595 }
9596
9597 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9598 {
9599         // TODO: optimize
9600         rsurface.passcolor4f = NULL;
9601         rsurface.passcolor4f_vertexbuffer = 0;
9602         rsurface.passcolor4f_bufferoffset = 0;
9603         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9604         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9605         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9606         GL_Color(r, g, b, a);
9607         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9608         RSurf_DrawBatch();
9609 }
9610
9611 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9612 {
9613         // TODO: optimize applyfog && applycolor case
9614         // just apply fog if necessary, and tint the fog color array if necessary
9615         rsurface.passcolor4f = NULL;
9616         rsurface.passcolor4f_vertexbuffer = 0;
9617         rsurface.passcolor4f_bufferoffset = 0;
9618         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9619         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9620         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9621         GL_Color(r, g, b, a);
9622         RSurf_DrawBatch();
9623 }
9624
9625 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9626 {
9627         // TODO: optimize
9628         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9629         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9630         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9631         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9632         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9633         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9634         GL_Color(r, g, b, a);
9635         RSurf_DrawBatch();
9636 }
9637
9638 static void RSurf_DrawBatch_GL11_ClampColor(void)
9639 {
9640         int i;
9641         const float *c1;
9642         float *c2;
9643         if (!rsurface.passcolor4f)
9644                 return;
9645         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9646         {
9647                 c2[0] = bound(0.0f, c1[0], 1.0f);
9648                 c2[1] = bound(0.0f, c1[1], 1.0f);
9649                 c2[2] = bound(0.0f, c1[2], 1.0f);
9650                 c2[3] = bound(0.0f, c1[3], 1.0f);
9651         }
9652 }
9653
9654 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9655 {
9656         int i;
9657         float f;
9658         const float *v;
9659         const float *n;
9660         float *c;
9661         //vec3_t eyedir;
9662
9663         // fake shading
9664         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9665         rsurface.passcolor4f_vertexbuffer = 0;
9666         rsurface.passcolor4f_bufferoffset = 0;
9667         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)
9668         {
9669                 f = -DotProduct(r_refdef.view.forward, n);
9670                 f = max(0, f);
9671                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9672                 f *= r_refdef.lightmapintensity;
9673                 Vector4Set(c, f, f, f, 1);
9674         }
9675 }
9676
9677 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9678 {
9679         RSurf_DrawBatch_GL11_ApplyFakeLight();
9680         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9681         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9682         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9683         GL_Color(r, g, b, a);
9684         RSurf_DrawBatch();
9685 }
9686
9687 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9688 {
9689         int i;
9690         float f;
9691         float alpha;
9692         const float *v;
9693         const float *n;
9694         float *c;
9695         vec3_t ambientcolor;
9696         vec3_t diffusecolor;
9697         vec3_t lightdir;
9698         // TODO: optimize
9699         // model lighting
9700         VectorCopy(rsurface.modellight_lightdir, lightdir);
9701         f = 0.5f * r_refdef.lightmapintensity;
9702         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9703         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9704         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9705         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9706         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9707         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9708         alpha = *a;
9709         if (VectorLength2(diffusecolor) > 0)
9710         {
9711                 // q3-style directional shading
9712                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9713                 rsurface.passcolor4f_vertexbuffer = 0;
9714                 rsurface.passcolor4f_bufferoffset = 0;
9715                 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)
9716                 {
9717                         if ((f = DotProduct(n, lightdir)) > 0)
9718                                 VectorMA(ambientcolor, f, diffusecolor, c);
9719                         else
9720                                 VectorCopy(ambientcolor, c);
9721                         c[3] = alpha;
9722                 }
9723                 *r = 1;
9724                 *g = 1;
9725                 *b = 1;
9726                 *a = 1;
9727                 *applycolor = false;
9728         }
9729         else
9730         {
9731                 *r = ambientcolor[0];
9732                 *g = ambientcolor[1];
9733                 *b = ambientcolor[2];
9734                 rsurface.passcolor4f = NULL;
9735                 rsurface.passcolor4f_vertexbuffer = 0;
9736                 rsurface.passcolor4f_bufferoffset = 0;
9737         }
9738 }
9739
9740 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9741 {
9742         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9743         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9744         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9745         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9746         GL_Color(r, g, b, a);
9747         RSurf_DrawBatch();
9748 }
9749
9750 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9751 {
9752         int i;
9753         float f;
9754         const float *v;
9755         float *c;
9756
9757         // fake shading
9758         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9759         rsurface.passcolor4f_vertexbuffer = 0;
9760         rsurface.passcolor4f_bufferoffset = 0;
9761
9762         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9763         {
9764                 f = 1 - RSurf_FogVertex(v);
9765                 c[0] = r;
9766                 c[1] = g;
9767                 c[2] = b;
9768                 c[3] = f * a;
9769         }
9770 }
9771
9772 void RSurf_SetupDepthAndCulling(void)
9773 {
9774         // submodels are biased to avoid z-fighting with world surfaces that they
9775         // may be exactly overlapping (avoids z-fighting artifacts on certain
9776         // doors and things in Quake maps)
9777         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9778         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9779         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9780         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9781 }
9782
9783 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9784 {
9785         // transparent sky would be ridiculous
9786         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9787                 return;
9788         R_SetupShader_Generic_NoTexture(false, false);
9789         skyrenderlater = true;
9790         RSurf_SetupDepthAndCulling();
9791         GL_DepthMask(true);
9792         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9793         // skymasking on them, and Quake3 never did sky masking (unlike
9794         // software Quake and software Quake2), so disable the sky masking
9795         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9796         // and skymasking also looks very bad when noclipping outside the
9797         // level, so don't use it then either.
9798         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9799         {
9800                 R_Mesh_ResetTextureState();
9801                 if (skyrendermasked)
9802                 {
9803                         R_SetupShader_DepthOrShadow(false, false);
9804                         // depth-only (masking)
9805                         GL_ColorMask(0,0,0,0);
9806                         // just to make sure that braindead drivers don't draw
9807                         // anything despite that colormask...
9808                         GL_BlendFunc(GL_ZERO, GL_ONE);
9809                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9810                         if (rsurface.batchvertex3fbuffer)
9811                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9812                         else
9813                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9814                 }
9815                 else
9816                 {
9817                         R_SetupShader_Generic_NoTexture(false, false);
9818                         // fog sky
9819                         GL_BlendFunc(GL_ONE, GL_ZERO);
9820                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9821                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9822                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9823                 }
9824                 RSurf_DrawBatch();
9825                 if (skyrendermasked)
9826                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9827         }
9828         R_Mesh_ResetTextureState();
9829         GL_Color(1, 1, 1, 1);
9830 }
9831
9832 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9833 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9834 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9835 {
9836         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9837                 return;
9838         if (prepass)
9839         {
9840                 // render screenspace normalmap to texture
9841                 GL_DepthMask(true);
9842                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9843                 RSurf_DrawBatch();
9844                 return;
9845         }
9846
9847         // bind lightmap texture
9848
9849         // water/refraction/reflection/camera surfaces have to be handled specially
9850         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9851         {
9852                 int start, end, startplaneindex;
9853                 for (start = 0;start < texturenumsurfaces;start = end)
9854                 {
9855                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9856                         if(startplaneindex < 0)
9857                         {
9858                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9859                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9860                                 end = start + 1;
9861                                 continue;
9862                         }
9863                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9864                                 ;
9865                         // now that we have a batch using the same planeindex, render it
9866                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9867                         {
9868                                 // render water or distortion background
9869                                 GL_DepthMask(true);
9870                                 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);
9871                                 RSurf_DrawBatch();
9872                                 // blend surface on top
9873                                 GL_DepthMask(false);
9874                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9875                                 RSurf_DrawBatch();
9876                         }
9877                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9878                         {
9879                                 // render surface with reflection texture as input
9880                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9881                                 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);
9882                                 RSurf_DrawBatch();
9883                         }
9884                 }
9885                 return;
9886         }
9887
9888         // render surface batch normally
9889         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9890         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);
9891         RSurf_DrawBatch();
9892 }
9893
9894 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9895 {
9896         // OpenGL 1.3 path - anything not completely ancient
9897         qboolean applycolor;
9898         qboolean applyfog;
9899         int layerindex;
9900         const texturelayer_t *layer;
9901         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);
9902         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9903
9904         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9905         {
9906                 vec4_t layercolor;
9907                 int layertexrgbscale;
9908                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9909                 {
9910                         if (layerindex == 0)
9911                                 GL_AlphaTest(true);
9912                         else
9913                         {
9914                                 GL_AlphaTest(false);
9915                                 GL_DepthFunc(GL_EQUAL);
9916                         }
9917                 }
9918                 GL_DepthMask(layer->depthmask && writedepth);
9919                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9920                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9921                 {
9922                         layertexrgbscale = 4;
9923                         VectorScale(layer->color, 0.25f, layercolor);
9924                 }
9925                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9926                 {
9927                         layertexrgbscale = 2;
9928                         VectorScale(layer->color, 0.5f, layercolor);
9929                 }
9930                 else
9931                 {
9932                         layertexrgbscale = 1;
9933                         VectorScale(layer->color, 1.0f, layercolor);
9934                 }
9935                 layercolor[3] = layer->color[3];
9936                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9937                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9938                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9939                 switch (layer->type)
9940                 {
9941                 case TEXTURELAYERTYPE_LITTEXTURE:
9942                         // single-pass lightmapped texture with 2x rgbscale
9943                         R_Mesh_TexBind(0, r_texture_white);
9944                         R_Mesh_TexMatrix(0, NULL);
9945                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9946                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9947                         R_Mesh_TexBind(1, layer->texture);
9948                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9949                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9950                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9951                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9952                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9953                         else if (FAKELIGHT_ENABLED)
9954                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9955                         else if (rsurface.uselightmaptexture)
9956                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9957                         else
9958                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9959                         break;
9960                 case TEXTURELAYERTYPE_TEXTURE:
9961                         // singletexture unlit texture with transparency support
9962                         R_Mesh_TexBind(0, layer->texture);
9963                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9964                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9965                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9966                         R_Mesh_TexBind(1, 0);
9967                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9968                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9969                         break;
9970                 case TEXTURELAYERTYPE_FOG:
9971                         // singletexture fogging
9972                         if (layer->texture)
9973                         {
9974                                 R_Mesh_TexBind(0, layer->texture);
9975                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9976                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9977                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9978                         }
9979                         else
9980                         {
9981                                 R_Mesh_TexBind(0, 0);
9982                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9983                         }
9984                         R_Mesh_TexBind(1, 0);
9985                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9986                         // generate a color array for the fog pass
9987                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9988                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9989                         RSurf_DrawBatch();
9990                         break;
9991                 default:
9992                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9993                 }
9994         }
9995         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9996         {
9997                 GL_DepthFunc(GL_LEQUAL);
9998                 GL_AlphaTest(false);
9999         }
10000 }
10001
10002 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10003 {
10004         // OpenGL 1.1 - crusty old voodoo path
10005         qboolean applyfog;
10006         int layerindex;
10007         const texturelayer_t *layer;
10008         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);
10009         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10010
10011         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10012         {
10013                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10014                 {
10015                         if (layerindex == 0)
10016                                 GL_AlphaTest(true);
10017                         else
10018                         {
10019                                 GL_AlphaTest(false);
10020                                 GL_DepthFunc(GL_EQUAL);
10021                         }
10022                 }
10023                 GL_DepthMask(layer->depthmask && writedepth);
10024                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10025                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10026                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10027                 switch (layer->type)
10028                 {
10029                 case TEXTURELAYERTYPE_LITTEXTURE:
10030                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10031                         {
10032                                 // two-pass lit texture with 2x rgbscale
10033                                 // first the lightmap pass
10034                                 R_Mesh_TexBind(0, r_texture_white);
10035                                 R_Mesh_TexMatrix(0, NULL);
10036                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10037                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10038                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10039                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10040                                 else if (FAKELIGHT_ENABLED)
10041                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10042                                 else if (rsurface.uselightmaptexture)
10043                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10044                                 else
10045                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10046                                 // then apply the texture to it
10047                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10048                                 R_Mesh_TexBind(0, layer->texture);
10049                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10050                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10051                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10052                                 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);
10053                         }
10054                         else
10055                         {
10056                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10057                                 R_Mesh_TexBind(0, layer->texture);
10058                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10059                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10060                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10061                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10062                                         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);
10063                                 else if (FAKELIGHT_ENABLED)
10064                                         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);
10065                                 else
10066                                         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);
10067                         }
10068                         break;
10069                 case TEXTURELAYERTYPE_TEXTURE:
10070                         // singletexture unlit texture with transparency support
10071                         R_Mesh_TexBind(0, layer->texture);
10072                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10073                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10074                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10075                         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);
10076                         break;
10077                 case TEXTURELAYERTYPE_FOG:
10078                         // singletexture fogging
10079                         if (layer->texture)
10080                         {
10081                                 R_Mesh_TexBind(0, layer->texture);
10082                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10083                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10084                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10085                         }
10086                         else
10087                         {
10088                                 R_Mesh_TexBind(0, 0);
10089                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10090                         }
10091                         // generate a color array for the fog pass
10092                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10093                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10094                         RSurf_DrawBatch();
10095                         break;
10096                 default:
10097                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10098                 }
10099         }
10100         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10101         {
10102                 GL_DepthFunc(GL_LEQUAL);
10103                 GL_AlphaTest(false);
10104         }
10105 }
10106
10107 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10108 {
10109         int vi;
10110         int j;
10111         r_vertexgeneric_t *batchvertex;
10112         float c[4];
10113
10114 //      R_Mesh_ResetTextureState();
10115         R_SetupShader_Generic_NoTexture(false, false);
10116
10117         if(rsurface.texture && rsurface.texture->currentskinframe)
10118         {
10119                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10120                 c[3] *= rsurface.texture->currentalpha;
10121         }
10122         else
10123         {
10124                 c[0] = 1;
10125                 c[1] = 0;
10126                 c[2] = 1;
10127                 c[3] = 1;
10128         }
10129
10130         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10131         {
10132                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10133                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10134                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10135         }
10136
10137         // brighten it up (as texture value 127 means "unlit")
10138         c[0] *= 2 * r_refdef.view.colorscale;
10139         c[1] *= 2 * r_refdef.view.colorscale;
10140         c[2] *= 2 * r_refdef.view.colorscale;
10141
10142         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10143                 c[3] *= r_wateralpha.value;
10144
10145         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10146         {
10147                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10148                 GL_DepthMask(false);
10149         }
10150         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10151         {
10152                 GL_BlendFunc(GL_ONE, GL_ONE);
10153                 GL_DepthMask(false);
10154         }
10155         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10156         {
10157                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10158                 GL_DepthMask(false);
10159         }
10160         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10161         {
10162                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10163                 GL_DepthMask(false);
10164         }
10165         else
10166         {
10167                 GL_BlendFunc(GL_ONE, GL_ZERO);
10168                 GL_DepthMask(writedepth);
10169         }
10170
10171         if (r_showsurfaces.integer == 3)
10172         {
10173                 rsurface.passcolor4f = NULL;
10174
10175                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10176                 {
10177                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10178
10179                         rsurface.passcolor4f = NULL;
10180                         rsurface.passcolor4f_vertexbuffer = 0;
10181                         rsurface.passcolor4f_bufferoffset = 0;
10182                 }
10183                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10184                 {
10185                         qboolean applycolor = true;
10186                         float one = 1.0;
10187
10188                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10189
10190                         r_refdef.lightmapintensity = 1;
10191                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10192                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10193                 }
10194                 else if (FAKELIGHT_ENABLED)
10195                 {
10196                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10197
10198                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10199                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10200                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10201                 }
10202                 else
10203                 {
10204                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10205
10206                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10207                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10208                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10209                 }
10210
10211                 if(!rsurface.passcolor4f)
10212                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10213
10214                 RSurf_DrawBatch_GL11_ApplyAmbient();
10215                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10216                 if(r_refdef.fogenabled)
10217                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10218                 RSurf_DrawBatch_GL11_ClampColor();
10219
10220                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10221                 R_SetupShader_Generic_NoTexture(false, false);
10222                 RSurf_DrawBatch();
10223         }
10224         else if (!r_refdef.view.showdebug)
10225         {
10226                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10227                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10228                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10229                 {
10230                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10231                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10232                 }
10233                 R_Mesh_PrepareVertices_Generic_Unlock();
10234                 RSurf_DrawBatch();
10235         }
10236         else if (r_showsurfaces.integer == 4)
10237         {
10238                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10239                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10240                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10241                 {
10242                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10243                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10244                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10245                 }
10246                 R_Mesh_PrepareVertices_Generic_Unlock();
10247                 RSurf_DrawBatch();
10248         }
10249         else if (r_showsurfaces.integer == 2)
10250         {
10251                 const int *e;
10252                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10253                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10254                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10255                 {
10256                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10257                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10258                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10259                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10260                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10261                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10262                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10263                 }
10264                 R_Mesh_PrepareVertices_Generic_Unlock();
10265                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10266         }
10267         else
10268         {
10269                 int texturesurfaceindex;
10270                 int k;
10271                 const msurface_t *surface;
10272                 float surfacecolor4f[4];
10273                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10274                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10275                 vi = 0;
10276                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10277                 {
10278                         surface = texturesurfacelist[texturesurfaceindex];
10279                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10280                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10281                         for (j = 0;j < surface->num_vertices;j++)
10282                         {
10283                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10284                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10285                                 vi++;
10286                         }
10287                 }
10288                 R_Mesh_PrepareVertices_Generic_Unlock();
10289                 RSurf_DrawBatch();
10290         }
10291 }
10292
10293 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10294 {
10295         CHECKGLERROR
10296         RSurf_SetupDepthAndCulling();
10297         if (r_showsurfaces.integer)
10298         {
10299                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10300                 return;
10301         }
10302         switch (vid.renderpath)
10303         {
10304         case RENDERPATH_GL20:
10305         case RENDERPATH_D3D9:
10306         case RENDERPATH_D3D10:
10307         case RENDERPATH_D3D11:
10308         case RENDERPATH_SOFT:
10309         case RENDERPATH_GLES2:
10310                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10311                 break;
10312         case RENDERPATH_GL13:
10313         case RENDERPATH_GLES1:
10314                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10315                 break;
10316         case RENDERPATH_GL11:
10317                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10318                 break;
10319         }
10320         CHECKGLERROR
10321 }
10322
10323 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10324 {
10325         CHECKGLERROR
10326         RSurf_SetupDepthAndCulling();
10327         if (r_showsurfaces.integer)
10328         {
10329                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10330                 return;
10331         }
10332         switch (vid.renderpath)
10333         {
10334         case RENDERPATH_GL20:
10335         case RENDERPATH_D3D9:
10336         case RENDERPATH_D3D10:
10337         case RENDERPATH_D3D11:
10338         case RENDERPATH_SOFT:
10339         case RENDERPATH_GLES2:
10340                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10341                 break;
10342         case RENDERPATH_GL13:
10343         case RENDERPATH_GLES1:
10344                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10345                 break;
10346         case RENDERPATH_GL11:
10347                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10348                 break;
10349         }
10350         CHECKGLERROR
10351 }
10352
10353 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10354 {
10355         int i, j;
10356         int texturenumsurfaces, endsurface;
10357         texture_t *texture;
10358         const msurface_t *surface;
10359         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10360
10361         // if the model is static it doesn't matter what value we give for
10362         // wantnormals and wanttangents, so this logic uses only rules applicable
10363         // to a model, knowing that they are meaningless otherwise
10364         if (ent == r_refdef.scene.worldentity)
10365                 RSurf_ActiveWorldEntity();
10366         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10367                 RSurf_ActiveModelEntity(ent, false, false, false);
10368         else
10369         {
10370                 switch (vid.renderpath)
10371                 {
10372                 case RENDERPATH_GL20:
10373                 case RENDERPATH_D3D9:
10374                 case RENDERPATH_D3D10:
10375                 case RENDERPATH_D3D11:
10376                 case RENDERPATH_SOFT:
10377                 case RENDERPATH_GLES2:
10378                         RSurf_ActiveModelEntity(ent, true, true, false);
10379                         break;
10380                 case RENDERPATH_GL11:
10381                 case RENDERPATH_GL13:
10382                 case RENDERPATH_GLES1:
10383                         RSurf_ActiveModelEntity(ent, true, false, false);
10384                         break;
10385                 }
10386         }
10387
10388         if (r_transparentdepthmasking.integer)
10389         {
10390                 qboolean setup = false;
10391                 for (i = 0;i < numsurfaces;i = j)
10392                 {
10393                         j = i + 1;
10394                         surface = rsurface.modelsurfaces + surfacelist[i];
10395                         texture = surface->texture;
10396                         rsurface.texture = R_GetCurrentTexture(texture);
10397                         rsurface.lightmaptexture = NULL;
10398                         rsurface.deluxemaptexture = NULL;
10399                         rsurface.uselightmaptexture = false;
10400                         // scan ahead until we find a different texture
10401                         endsurface = min(i + 1024, numsurfaces);
10402                         texturenumsurfaces = 0;
10403                         texturesurfacelist[texturenumsurfaces++] = surface;
10404                         for (;j < endsurface;j++)
10405                         {
10406                                 surface = rsurface.modelsurfaces + surfacelist[j];
10407                                 if (texture != surface->texture)
10408                                         break;
10409                                 texturesurfacelist[texturenumsurfaces++] = surface;
10410                         }
10411                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10412                                 continue;
10413                         // render the range of surfaces as depth
10414                         if (!setup)
10415                         {
10416                                 setup = true;
10417                                 GL_ColorMask(0,0,0,0);
10418                                 GL_Color(1,1,1,1);
10419                                 GL_DepthTest(true);
10420                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10421                                 GL_DepthMask(true);
10422 //                              R_Mesh_ResetTextureState();
10423                                 R_SetupShader_DepthOrShadow(false, false);
10424                         }
10425                         RSurf_SetupDepthAndCulling();
10426                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10427                         if (rsurface.batchvertex3fbuffer)
10428                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10429                         else
10430                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10431                         RSurf_DrawBatch();
10432                 }
10433                 if (setup)
10434                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10435         }
10436
10437         for (i = 0;i < numsurfaces;i = j)
10438         {
10439                 j = i + 1;
10440                 surface = rsurface.modelsurfaces + surfacelist[i];
10441                 texture = surface->texture;
10442                 rsurface.texture = R_GetCurrentTexture(texture);
10443                 // scan ahead until we find a different texture
10444                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10445                 texturenumsurfaces = 0;
10446                 texturesurfacelist[texturenumsurfaces++] = surface;
10447                 if(FAKELIGHT_ENABLED)
10448                 {
10449                         rsurface.lightmaptexture = NULL;
10450                         rsurface.deluxemaptexture = NULL;
10451                         rsurface.uselightmaptexture = false;
10452                         for (;j < endsurface;j++)
10453                         {
10454                                 surface = rsurface.modelsurfaces + surfacelist[j];
10455                                 if (texture != surface->texture)
10456                                         break;
10457                                 texturesurfacelist[texturenumsurfaces++] = surface;
10458                         }
10459                 }
10460                 else
10461                 {
10462                         rsurface.lightmaptexture = surface->lightmaptexture;
10463                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10464                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10465                         for (;j < endsurface;j++)
10466                         {
10467                                 surface = rsurface.modelsurfaces + surfacelist[j];
10468                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10469                                         break;
10470                                 texturesurfacelist[texturenumsurfaces++] = surface;
10471                         }
10472                 }
10473                 // render the range of surfaces
10474                 if (ent == r_refdef.scene.worldentity)
10475                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10476                 else
10477                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10478         }
10479         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10480 }
10481
10482 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10483 {
10484         // transparent surfaces get pushed off into the transparent queue
10485         int surfacelistindex;
10486         const msurface_t *surface;
10487         vec3_t tempcenter, center;
10488         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10489         {
10490                 surface = texturesurfacelist[surfacelistindex];
10491                 if (r_transparent_sortsurfacesbynearest.integer)
10492                 {
10493                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10494                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10495                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10496                 }
10497                 else
10498                 {
10499                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10500                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10501                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10502                 }
10503                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10504                 if (rsurface.entity->transparent_offset) // transparent offset
10505                 {
10506                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10507                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10508                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10509                 }
10510                 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);
10511         }
10512 }
10513
10514 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10515 {
10516         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10517                 return;
10518         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10519                 return;
10520         RSurf_SetupDepthAndCulling();
10521         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10522         if (rsurface.batchvertex3fbuffer)
10523                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10524         else
10525                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10526         RSurf_DrawBatch();
10527 }
10528
10529 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10530 {
10531         CHECKGLERROR
10532         if (depthonly)
10533                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10534         else if (prepass)
10535         {
10536                 if (!rsurface.texture->currentnumlayers)
10537                         return;
10538                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10539                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10540                 else
10541                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10542         }
10543         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10544                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10545         else if (!rsurface.texture->currentnumlayers)
10546                 return;
10547         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10548         {
10549                 // in the deferred case, transparent surfaces were queued during prepass
10550                 if (!r_shadow_usingdeferredprepass)
10551                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10552         }
10553         else
10554         {
10555                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10556                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10557         }
10558         CHECKGLERROR
10559 }
10560
10561 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10562 {
10563         int i, j;
10564         texture_t *texture;
10565         R_FrameData_SetMark();
10566         // break the surface list down into batches by texture and use of lightmapping
10567         for (i = 0;i < numsurfaces;i = j)
10568         {
10569                 j = i + 1;
10570                 // texture is the base texture pointer, rsurface.texture is the
10571                 // current frame/skin the texture is directing us to use (for example
10572                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10573                 // use skin 1 instead)
10574                 texture = surfacelist[i]->texture;
10575                 rsurface.texture = R_GetCurrentTexture(texture);
10576                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10577                 {
10578                         // if this texture is not the kind we want, skip ahead to the next one
10579                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10580                                 ;
10581                         continue;
10582                 }
10583                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10584                 {
10585                         rsurface.lightmaptexture = NULL;
10586                         rsurface.deluxemaptexture = NULL;
10587                         rsurface.uselightmaptexture = false;
10588                         // simply scan ahead until we find a different texture or lightmap state
10589                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10590                                 ;
10591                 }
10592                 else
10593                 {
10594                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10595                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10596                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10597                         // simply scan ahead until we find a different texture or lightmap state
10598                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10599                                 ;
10600                 }
10601                 // render the range of surfaces
10602                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10603         }
10604         R_FrameData_ReturnToMark();
10605 }
10606
10607 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10608 {
10609         CHECKGLERROR
10610         if (depthonly)
10611                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10612         else if (prepass)
10613         {
10614                 if (!rsurface.texture->currentnumlayers)
10615                         return;
10616                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10617                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10618                 else
10619                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10620         }
10621         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10622                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10623         else if (!rsurface.texture->currentnumlayers)
10624                 return;
10625         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10626         {
10627                 // in the deferred case, transparent surfaces were queued during prepass
10628                 if (!r_shadow_usingdeferredprepass)
10629                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10630         }
10631         else
10632         {
10633                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10634                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10635         }
10636         CHECKGLERROR
10637 }
10638
10639 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10640 {
10641         int i, j;
10642         texture_t *texture;
10643         R_FrameData_SetMark();
10644         // break the surface list down into batches by texture and use of lightmapping
10645         for (i = 0;i < numsurfaces;i = j)
10646         {
10647                 j = i + 1;
10648                 // texture is the base texture pointer, rsurface.texture is the
10649                 // current frame/skin the texture is directing us to use (for example
10650                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10651                 // use skin 1 instead)
10652                 texture = surfacelist[i]->texture;
10653                 rsurface.texture = R_GetCurrentTexture(texture);
10654                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10655                 {
10656                         // if this texture is not the kind we want, skip ahead to the next one
10657                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10658                                 ;
10659                         continue;
10660                 }
10661                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10662                 {
10663                         rsurface.lightmaptexture = NULL;
10664                         rsurface.deluxemaptexture = NULL;
10665                         rsurface.uselightmaptexture = false;
10666                         // simply scan ahead until we find a different texture or lightmap state
10667                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10668                                 ;
10669                 }
10670                 else
10671                 {
10672                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10673                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10674                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10675                         // simply scan ahead until we find a different texture or lightmap state
10676                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10677                                 ;
10678                 }
10679                 // render the range of surfaces
10680                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10681         }
10682         R_FrameData_ReturnToMark();
10683 }
10684
10685 float locboxvertex3f[6*4*3] =
10686 {
10687         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10688         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10689         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10690         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10691         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10692         1,0,0, 0,0,0, 0,1,0, 1,1,0
10693 };
10694
10695 unsigned short locboxelements[6*2*3] =
10696 {
10697          0, 1, 2, 0, 2, 3,
10698          4, 5, 6, 4, 6, 7,
10699          8, 9,10, 8,10,11,
10700         12,13,14, 12,14,15,
10701         16,17,18, 16,18,19,
10702         20,21,22, 20,22,23
10703 };
10704
10705 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10706 {
10707         int i, j;
10708         cl_locnode_t *loc = (cl_locnode_t *)ent;
10709         vec3_t mins, size;
10710         float vertex3f[6*4*3];
10711         CHECKGLERROR
10712         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10713         GL_DepthMask(false);
10714         GL_DepthRange(0, 1);
10715         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10716         GL_DepthTest(true);
10717         GL_CullFace(GL_NONE);
10718         R_EntityMatrix(&identitymatrix);
10719
10720 //      R_Mesh_ResetTextureState();
10721
10722         i = surfacelist[0];
10723         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10724                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10725                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10726                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10727
10728         if (VectorCompare(loc->mins, loc->maxs))
10729         {
10730                 VectorSet(size, 2, 2, 2);
10731                 VectorMA(loc->mins, -0.5f, size, mins);
10732         }
10733         else
10734         {
10735                 VectorCopy(loc->mins, mins);
10736                 VectorSubtract(loc->maxs, loc->mins, size);
10737         }
10738
10739         for (i = 0;i < 6*4*3;)
10740                 for (j = 0;j < 3;j++, i++)
10741                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10742
10743         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10744         R_SetupShader_Generic_NoTexture(false, false);
10745         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10746 }
10747
10748 void R_DrawLocs(void)
10749 {
10750         int index;
10751         cl_locnode_t *loc, *nearestloc;
10752         vec3_t center;
10753         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10754         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10755         {
10756                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10757                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10758         }
10759 }
10760
10761 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10762 {
10763         if (decalsystem->decals)
10764                 Mem_Free(decalsystem->decals);
10765         memset(decalsystem, 0, sizeof(*decalsystem));
10766 }
10767
10768 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)
10769 {
10770         tridecal_t *decal;
10771         tridecal_t *decals;
10772         int i;
10773
10774         // expand or initialize the system
10775         if (decalsystem->maxdecals <= decalsystem->numdecals)
10776         {
10777                 decalsystem_t old = *decalsystem;
10778                 qboolean useshortelements;
10779                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10780                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10781                 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)));
10782                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10783                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10784                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10785                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10786                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10787                 if (decalsystem->numdecals)
10788                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10789                 if (old.decals)
10790                         Mem_Free(old.decals);
10791                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10792                         decalsystem->element3i[i] = i;
10793                 if (useshortelements)
10794                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10795                                 decalsystem->element3s[i] = i;
10796         }
10797
10798         // grab a decal and search for another free slot for the next one
10799         decals = decalsystem->decals;
10800         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10801         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10802                 ;
10803         decalsystem->freedecal = i;
10804         if (decalsystem->numdecals <= i)
10805                 decalsystem->numdecals = i + 1;
10806
10807         // initialize the decal
10808         decal->lived = 0;
10809         decal->triangleindex = triangleindex;
10810         decal->surfaceindex = surfaceindex;
10811         decal->decalsequence = decalsequence;
10812         decal->color4f[0][0] = c0[0];
10813         decal->color4f[0][1] = c0[1];
10814         decal->color4f[0][2] = c0[2];
10815         decal->color4f[0][3] = 1;
10816         decal->color4f[1][0] = c1[0];
10817         decal->color4f[1][1] = c1[1];
10818         decal->color4f[1][2] = c1[2];
10819         decal->color4f[1][3] = 1;
10820         decal->color4f[2][0] = c2[0];
10821         decal->color4f[2][1] = c2[1];
10822         decal->color4f[2][2] = c2[2];
10823         decal->color4f[2][3] = 1;
10824         decal->vertex3f[0][0] = v0[0];
10825         decal->vertex3f[0][1] = v0[1];
10826         decal->vertex3f[0][2] = v0[2];
10827         decal->vertex3f[1][0] = v1[0];
10828         decal->vertex3f[1][1] = v1[1];
10829         decal->vertex3f[1][2] = v1[2];
10830         decal->vertex3f[2][0] = v2[0];
10831         decal->vertex3f[2][1] = v2[1];
10832         decal->vertex3f[2][2] = v2[2];
10833         decal->texcoord2f[0][0] = t0[0];
10834         decal->texcoord2f[0][1] = t0[1];
10835         decal->texcoord2f[1][0] = t1[0];
10836         decal->texcoord2f[1][1] = t1[1];
10837         decal->texcoord2f[2][0] = t2[0];
10838         decal->texcoord2f[2][1] = t2[1];
10839         TriangleNormal(v0, v1, v2, decal->plane);
10840         VectorNormalize(decal->plane);
10841         decal->plane[3] = DotProduct(v0, decal->plane);
10842 }
10843
10844 extern cvar_t cl_decals_bias;
10845 extern cvar_t cl_decals_models;
10846 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10847 // baseparms, parms, temps
10848 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)
10849 {
10850         int cornerindex;
10851         int index;
10852         float v[9][3];
10853         const float *vertex3f;
10854         const float *normal3f;
10855         int numpoints;
10856         float points[2][9][3];
10857         float temp[3];
10858         float tc[9][2];
10859         float f;
10860         float c[9][4];
10861         const int *e;
10862
10863         e = rsurface.modelelement3i + 3*triangleindex;
10864
10865         vertex3f = rsurface.modelvertex3f;
10866         normal3f = rsurface.modelnormal3f;
10867
10868         if (normal3f)
10869         {
10870                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10871                 {
10872                         index = 3*e[cornerindex];
10873                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10874                 }
10875         }
10876         else
10877         {
10878                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10879                 {
10880                         index = 3*e[cornerindex];
10881                         VectorCopy(vertex3f + index, v[cornerindex]);
10882                 }
10883         }
10884
10885         // cull backfaces
10886         //TriangleNormal(v[0], v[1], v[2], normal);
10887         //if (DotProduct(normal, localnormal) < 0.0f)
10888         //      continue;
10889         // clip by each of the box planes formed from the projection matrix
10890         // if anything survives, we emit the decal
10891         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]);
10892         if (numpoints < 3)
10893                 return;
10894         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]);
10895         if (numpoints < 3)
10896                 return;
10897         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]);
10898         if (numpoints < 3)
10899                 return;
10900         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]);
10901         if (numpoints < 3)
10902                 return;
10903         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]);
10904         if (numpoints < 3)
10905                 return;
10906         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]);
10907         if (numpoints < 3)
10908                 return;
10909         // some part of the triangle survived, so we have to accept it...
10910         if (dynamic)
10911         {
10912                 // dynamic always uses the original triangle
10913                 numpoints = 3;
10914                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10915                 {
10916                         index = 3*e[cornerindex];
10917                         VectorCopy(vertex3f + index, v[cornerindex]);
10918                 }
10919         }
10920         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10921         {
10922                 // convert vertex positions to texcoords
10923                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10924                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10925                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10926                 // calculate distance fade from the projection origin
10927                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10928                 f = bound(0.0f, f, 1.0f);
10929                 c[cornerindex][0] = r * f;
10930                 c[cornerindex][1] = g * f;
10931                 c[cornerindex][2] = b * f;
10932                 c[cornerindex][3] = 1.0f;
10933                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10934         }
10935         if (dynamic)
10936                 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);
10937         else
10938                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10939                         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);
10940 }
10941 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)
10942 {
10943         matrix4x4_t projection;
10944         decalsystem_t *decalsystem;
10945         qboolean dynamic;
10946         dp_model_t *model;
10947         const msurface_t *surface;
10948         const msurface_t *surfaces;
10949         const int *surfacelist;
10950         const texture_t *texture;
10951         int numtriangles;
10952         int numsurfacelist;
10953         int surfacelistindex;
10954         int surfaceindex;
10955         int triangleindex;
10956         float localorigin[3];
10957         float localnormal[3];
10958         float localmins[3];
10959         float localmaxs[3];
10960         float localsize;
10961         //float normal[3];
10962         float planes[6][4];
10963         float angles[3];
10964         bih_t *bih;
10965         int bih_triangles_count;
10966         int bih_triangles[256];
10967         int bih_surfaces[256];
10968
10969         decalsystem = &ent->decalsystem;
10970         model = ent->model;
10971         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10972         {
10973                 R_DecalSystem_Reset(&ent->decalsystem);
10974                 return;
10975         }
10976
10977         if (!model->brush.data_leafs && !cl_decals_models.integer)
10978         {
10979                 if (decalsystem->model)
10980                         R_DecalSystem_Reset(decalsystem);
10981                 return;
10982         }
10983
10984         if (decalsystem->model != model)
10985                 R_DecalSystem_Reset(decalsystem);
10986         decalsystem->model = model;
10987
10988         RSurf_ActiveModelEntity(ent, true, false, false);
10989
10990         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10991         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10992         VectorNormalize(localnormal);
10993         localsize = worldsize*rsurface.inversematrixscale;
10994         localmins[0] = localorigin[0] - localsize;
10995         localmins[1] = localorigin[1] - localsize;
10996         localmins[2] = localorigin[2] - localsize;
10997         localmaxs[0] = localorigin[0] + localsize;
10998         localmaxs[1] = localorigin[1] + localsize;
10999         localmaxs[2] = localorigin[2] + localsize;
11000
11001         //VectorCopy(localnormal, planes[4]);
11002         //VectorVectors(planes[4], planes[2], planes[0]);
11003         AnglesFromVectors(angles, localnormal, NULL, false);
11004         AngleVectors(angles, planes[0], planes[2], planes[4]);
11005         VectorNegate(planes[0], planes[1]);
11006         VectorNegate(planes[2], planes[3]);
11007         VectorNegate(planes[4], planes[5]);
11008         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11009         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11010         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11011         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11012         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11013         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11014
11015 #if 1
11016 // works
11017 {
11018         matrix4x4_t forwardprojection;
11019         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11020         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11021 }
11022 #else
11023 // broken
11024 {
11025         float projectionvector[4][3];
11026         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11027         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11028         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11029         projectionvector[0][0] = planes[0][0] * ilocalsize;
11030         projectionvector[0][1] = planes[1][0] * ilocalsize;
11031         projectionvector[0][2] = planes[2][0] * ilocalsize;
11032         projectionvector[1][0] = planes[0][1] * ilocalsize;
11033         projectionvector[1][1] = planes[1][1] * ilocalsize;
11034         projectionvector[1][2] = planes[2][1] * ilocalsize;
11035         projectionvector[2][0] = planes[0][2] * ilocalsize;
11036         projectionvector[2][1] = planes[1][2] * ilocalsize;
11037         projectionvector[2][2] = planes[2][2] * ilocalsize;
11038         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11039         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11040         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11041         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11042 }
11043 #endif
11044
11045         dynamic = model->surfmesh.isanimated;
11046         numsurfacelist = model->nummodelsurfaces;
11047         surfacelist = model->sortedmodelsurfaces;
11048         surfaces = model->data_surfaces;
11049
11050         bih = NULL;
11051         bih_triangles_count = -1;
11052         if(!dynamic)
11053         {
11054                 if(model->render_bih.numleafs)
11055                         bih = &model->render_bih;
11056                 else if(model->collision_bih.numleafs)
11057                         bih = &model->collision_bih;
11058         }
11059         if(bih)
11060                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11061         if(bih_triangles_count == 0)
11062                 return;
11063         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11064                 return;
11065         if(bih_triangles_count > 0)
11066         {
11067                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11068                 {
11069                         surfaceindex = bih_surfaces[triangleindex];
11070                         surface = surfaces + surfaceindex;
11071                         texture = surface->texture;
11072                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11073                                 continue;
11074                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11075                                 continue;
11076                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11077                 }
11078         }
11079         else
11080         {
11081                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11082                 {
11083                         surfaceindex = surfacelist[surfacelistindex];
11084                         surface = surfaces + surfaceindex;
11085                         // check cull box first because it rejects more than any other check
11086                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11087                                 continue;
11088                         // skip transparent surfaces
11089                         texture = surface->texture;
11090                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11091                                 continue;
11092                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11093                                 continue;
11094                         numtriangles = surface->num_triangles;
11095                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11096                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11097                 }
11098         }
11099 }
11100
11101 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11102 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)
11103 {
11104         int renderentityindex;
11105         float worldmins[3];
11106         float worldmaxs[3];
11107         entity_render_t *ent;
11108
11109         if (!cl_decals_newsystem.integer)
11110                 return;
11111
11112         worldmins[0] = worldorigin[0] - worldsize;
11113         worldmins[1] = worldorigin[1] - worldsize;
11114         worldmins[2] = worldorigin[2] - worldsize;
11115         worldmaxs[0] = worldorigin[0] + worldsize;
11116         worldmaxs[1] = worldorigin[1] + worldsize;
11117         worldmaxs[2] = worldorigin[2] + worldsize;
11118
11119         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11120
11121         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11122         {
11123                 ent = r_refdef.scene.entities[renderentityindex];
11124                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11125                         continue;
11126
11127                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11128         }
11129 }
11130
11131 typedef struct r_decalsystem_splatqueue_s
11132 {
11133         vec3_t worldorigin;
11134         vec3_t worldnormal;
11135         float color[4];
11136         float tcrange[4];
11137         float worldsize;
11138         int decalsequence;
11139 }
11140 r_decalsystem_splatqueue_t;
11141
11142 int r_decalsystem_numqueued = 0;
11143 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11144
11145 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)
11146 {
11147         r_decalsystem_splatqueue_t *queue;
11148
11149         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11150                 return;
11151
11152         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11153         VectorCopy(worldorigin, queue->worldorigin);
11154         VectorCopy(worldnormal, queue->worldnormal);
11155         Vector4Set(queue->color, r, g, b, a);
11156         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11157         queue->worldsize = worldsize;
11158         queue->decalsequence = cl.decalsequence++;
11159 }
11160
11161 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11162 {
11163         int i;
11164         r_decalsystem_splatqueue_t *queue;
11165
11166         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11167                 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);
11168         r_decalsystem_numqueued = 0;
11169 }
11170
11171 extern cvar_t cl_decals_max;
11172 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11173 {
11174         int i;
11175         decalsystem_t *decalsystem = &ent->decalsystem;
11176         int numdecals;
11177         int killsequence;
11178         tridecal_t *decal;
11179         float frametime;
11180         float lifetime;
11181
11182         if (!decalsystem->numdecals)
11183                 return;
11184
11185         if (r_showsurfaces.integer)
11186                 return;
11187
11188         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11189         {
11190                 R_DecalSystem_Reset(decalsystem);
11191                 return;
11192         }
11193
11194         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11195         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11196
11197         if (decalsystem->lastupdatetime)
11198                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11199         else
11200                 frametime = 0;
11201         decalsystem->lastupdatetime = r_refdef.scene.time;
11202         numdecals = decalsystem->numdecals;
11203
11204         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11205         {
11206                 if (decal->color4f[0][3])
11207                 {
11208                         decal->lived += frametime;
11209                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11210                         {
11211                                 memset(decal, 0, sizeof(*decal));
11212                                 if (decalsystem->freedecal > i)
11213                                         decalsystem->freedecal = i;
11214                         }
11215                 }
11216         }
11217         decal = decalsystem->decals;
11218         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11219                 numdecals--;
11220
11221         // collapse the array by shuffling the tail decals into the gaps
11222         for (;;)
11223         {
11224                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11225                         decalsystem->freedecal++;
11226                 if (decalsystem->freedecal == numdecals)
11227                         break;
11228                 decal[decalsystem->freedecal] = decal[--numdecals];
11229         }
11230
11231         decalsystem->numdecals = numdecals;
11232
11233         if (numdecals <= 0)
11234         {
11235                 // if there are no decals left, reset decalsystem
11236                 R_DecalSystem_Reset(decalsystem);
11237         }
11238 }
11239
11240 extern skinframe_t *decalskinframe;
11241 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11242 {
11243         int i;
11244         decalsystem_t *decalsystem = &ent->decalsystem;
11245         int numdecals;
11246         tridecal_t *decal;
11247         float faderate;
11248         float alpha;
11249         float *v3f;
11250         float *c4f;
11251         float *t2f;
11252         const int *e;
11253         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11254         int numtris = 0;
11255
11256         numdecals = decalsystem->numdecals;
11257         if (!numdecals)
11258                 return;
11259
11260         if (r_showsurfaces.integer)
11261                 return;
11262
11263         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11264         {
11265                 R_DecalSystem_Reset(decalsystem);
11266                 return;
11267         }
11268
11269         // if the model is static it doesn't matter what value we give for
11270         // wantnormals and wanttangents, so this logic uses only rules applicable
11271         // to a model, knowing that they are meaningless otherwise
11272         if (ent == r_refdef.scene.worldentity)
11273                 RSurf_ActiveWorldEntity();
11274         else
11275                 RSurf_ActiveModelEntity(ent, false, false, false);
11276
11277         decalsystem->lastupdatetime = r_refdef.scene.time;
11278
11279         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11280
11281         // update vertex positions for animated models
11282         v3f = decalsystem->vertex3f;
11283         c4f = decalsystem->color4f;
11284         t2f = decalsystem->texcoord2f;
11285         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11286         {
11287                 if (!decal->color4f[0][3])
11288                         continue;
11289
11290                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11291                         continue;
11292
11293                 // skip backfaces
11294                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11295                         continue;
11296
11297                 // update color values for fading decals
11298                 if (decal->lived >= cl_decals_time.value)
11299                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11300                 else
11301                         alpha = 1.0f;
11302
11303                 c4f[ 0] = decal->color4f[0][0] * alpha;
11304                 c4f[ 1] = decal->color4f[0][1] * alpha;
11305                 c4f[ 2] = decal->color4f[0][2] * alpha;
11306                 c4f[ 3] = 1;
11307                 c4f[ 4] = decal->color4f[1][0] * alpha;
11308                 c4f[ 5] = decal->color4f[1][1] * alpha;
11309                 c4f[ 6] = decal->color4f[1][2] * alpha;
11310                 c4f[ 7] = 1;
11311                 c4f[ 8] = decal->color4f[2][0] * alpha;
11312                 c4f[ 9] = decal->color4f[2][1] * alpha;
11313                 c4f[10] = decal->color4f[2][2] * alpha;
11314                 c4f[11] = 1;
11315
11316                 t2f[0] = decal->texcoord2f[0][0];
11317                 t2f[1] = decal->texcoord2f[0][1];
11318                 t2f[2] = decal->texcoord2f[1][0];
11319                 t2f[3] = decal->texcoord2f[1][1];
11320                 t2f[4] = decal->texcoord2f[2][0];
11321                 t2f[5] = decal->texcoord2f[2][1];
11322
11323                 // update vertex positions for animated models
11324                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11325                 {
11326                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11327                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11328                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11329                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11330                 }
11331                 else
11332                 {
11333                         VectorCopy(decal->vertex3f[0], v3f);
11334                         VectorCopy(decal->vertex3f[1], v3f + 3);
11335                         VectorCopy(decal->vertex3f[2], v3f + 6);
11336                 }
11337
11338                 if (r_refdef.fogenabled)
11339                 {
11340                         alpha = RSurf_FogVertex(v3f);
11341                         VectorScale(c4f, alpha, c4f);
11342                         alpha = RSurf_FogVertex(v3f + 3);
11343                         VectorScale(c4f + 4, alpha, c4f + 4);
11344                         alpha = RSurf_FogVertex(v3f + 6);
11345                         VectorScale(c4f + 8, alpha, c4f + 8);
11346                 }
11347
11348                 v3f += 9;
11349                 c4f += 12;
11350                 t2f += 6;
11351                 numtris++;
11352         }
11353
11354         if (numtris > 0)
11355         {
11356                 r_refdef.stats.drawndecals += numtris;
11357
11358                 // now render the decals all at once
11359                 // (this assumes they all use one particle font texture!)
11360                 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);
11361 //              R_Mesh_ResetTextureState();
11362                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11363                 GL_DepthMask(false);
11364                 GL_DepthRange(0, 1);
11365                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11366                 GL_DepthTest(true);
11367                 GL_CullFace(GL_NONE);
11368                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11369                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11370                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11371         }
11372 }
11373
11374 static void R_DrawModelDecals(void)
11375 {
11376         int i, numdecals;
11377
11378         // fade faster when there are too many decals
11379         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11380         for (i = 0;i < r_refdef.scene.numentities;i++)
11381                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11382
11383         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11384         for (i = 0;i < r_refdef.scene.numentities;i++)
11385                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11386                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11387
11388         R_DecalSystem_ApplySplatEntitiesQueue();
11389
11390         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11391         for (i = 0;i < r_refdef.scene.numentities;i++)
11392                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11393
11394         r_refdef.stats.totaldecals += numdecals;
11395
11396         if (r_showsurfaces.integer)
11397                 return;
11398
11399         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11400
11401         for (i = 0;i < r_refdef.scene.numentities;i++)
11402         {
11403                 if (!r_refdef.viewcache.entityvisible[i])
11404                         continue;
11405                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11406                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11407         }
11408 }
11409
11410 extern cvar_t mod_collision_bih;
11411 static void R_DrawDebugModel(void)
11412 {
11413         entity_render_t *ent = rsurface.entity;
11414         int i, j, k, l, flagsmask;
11415         const msurface_t *surface;
11416         dp_model_t *model = ent->model;
11417         vec3_t v;
11418
11419         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11420                 return;
11421
11422         if (r_showoverdraw.value > 0)
11423         {
11424                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11425                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11426                 R_SetupShader_Generic_NoTexture(false, false);
11427                 GL_DepthTest(false);
11428                 GL_DepthMask(false);
11429                 GL_DepthRange(0, 1);
11430                 GL_BlendFunc(GL_ONE, GL_ONE);
11431                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11432                 {
11433                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11434                                 continue;
11435                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11436                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11437                         {
11438                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11439                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11440                                 if (!rsurface.texture->currentlayers->depthmask)
11441                                         GL_Color(c, 0, 0, 1.0f);
11442                                 else if (ent == r_refdef.scene.worldentity)
11443                                         GL_Color(c, c, c, 1.0f);
11444                                 else
11445                                         GL_Color(0, c, 0, 1.0f);
11446                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11447                                 RSurf_DrawBatch();
11448                         }
11449                 }
11450                 rsurface.texture = NULL;
11451         }
11452
11453         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11454
11455 //      R_Mesh_ResetTextureState();
11456         R_SetupShader_Generic_NoTexture(false, false);
11457         GL_DepthRange(0, 1);
11458         GL_DepthTest(!r_showdisabledepthtest.integer);
11459         GL_DepthMask(false);
11460         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11461
11462         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11463         {
11464                 int triangleindex;
11465                 int bihleafindex;
11466                 qboolean cullbox = false;
11467                 const q3mbrush_t *brush;
11468                 const bih_t *bih = &model->collision_bih;
11469                 const bih_leaf_t *bihleaf;
11470                 float vertex3f[3][3];
11471                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11472                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11473                 {
11474                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11475                                 continue;
11476                         switch (bihleaf->type)
11477                         {
11478                         case BIH_BRUSH:
11479                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11480                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11481                                 {
11482                                         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);
11483                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11484                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11485                                 }
11486                                 break;
11487                         case BIH_COLLISIONTRIANGLE:
11488                                 triangleindex = bihleaf->itemindex;
11489                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11490                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11491                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11492                                 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);
11493                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11494                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11495                                 break;
11496                         case BIH_RENDERTRIANGLE:
11497                                 triangleindex = bihleaf->itemindex;
11498                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11499                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11500                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11501                                 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);
11502                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11503                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11504                                 break;
11505                         }
11506                 }
11507         }
11508
11509         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11510
11511 #ifndef USE_GLES2
11512         if (r_showtris.integer && qglPolygonMode)
11513         {
11514                 if (r_showdisabledepthtest.integer)
11515                 {
11516                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11517                         GL_DepthMask(false);
11518                 }
11519                 else
11520                 {
11521                         GL_BlendFunc(GL_ONE, GL_ZERO);
11522                         GL_DepthMask(true);
11523                 }
11524                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11525                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11526                 {
11527                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11528                                 continue;
11529                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11530                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11531                         {
11532                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11533                                 if (!rsurface.texture->currentlayers->depthmask)
11534                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11535                                 else if (ent == r_refdef.scene.worldentity)
11536                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11537                                 else
11538                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11539                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11540                                 RSurf_DrawBatch();
11541                         }
11542                 }
11543                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11544                 rsurface.texture = NULL;
11545         }
11546
11547         if (r_shownormals.value != 0 && qglBegin)
11548         {
11549                 if (r_showdisabledepthtest.integer)
11550                 {
11551                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11552                         GL_DepthMask(false);
11553                 }
11554                 else
11555                 {
11556                         GL_BlendFunc(GL_ONE, GL_ZERO);
11557                         GL_DepthMask(true);
11558                 }
11559                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11560                 {
11561                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11562                                 continue;
11563                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11564                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11565                         {
11566                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11567                                 qglBegin(GL_LINES);
11568                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11569                                 {
11570                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11571                                         {
11572                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11573                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11574                                                 qglVertex3f(v[0], v[1], v[2]);
11575                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11576                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11577                                                 qglVertex3f(v[0], v[1], v[2]);
11578                                         }
11579                                 }
11580                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11581                                 {
11582                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11583                                         {
11584                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11585                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11586                                                 qglVertex3f(v[0], v[1], v[2]);
11587                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11588                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11589                                                 qglVertex3f(v[0], v[1], v[2]);
11590                                         }
11591                                 }
11592                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11593                                 {
11594                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11595                                         {
11596                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11597                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11598                                                 qglVertex3f(v[0], v[1], v[2]);
11599                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11600                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11601                                                 qglVertex3f(v[0], v[1], v[2]);
11602                                         }
11603                                 }
11604                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11605                                 {
11606                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11607                                         {
11608                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11609                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11610                                                 qglVertex3f(v[0], v[1], v[2]);
11611                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11612                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11613                                                 qglVertex3f(v[0], v[1], v[2]);
11614                                         }
11615                                 }
11616                                 qglEnd();
11617                                 CHECKGLERROR
11618                         }
11619                 }
11620                 rsurface.texture = NULL;
11621         }
11622 #endif
11623 }
11624
11625 int r_maxsurfacelist = 0;
11626 const msurface_t **r_surfacelist = NULL;
11627 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11628 {
11629         int i, j, endj, flagsmask;
11630         dp_model_t *model = r_refdef.scene.worldmodel;
11631         msurface_t *surfaces;
11632         unsigned char *update;
11633         int numsurfacelist = 0;
11634         if (model == NULL)
11635                 return;
11636
11637         if (r_maxsurfacelist < model->num_surfaces)
11638         {
11639                 r_maxsurfacelist = model->num_surfaces;
11640                 if (r_surfacelist)
11641                         Mem_Free((msurface_t**)r_surfacelist);
11642                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11643         }
11644
11645         RSurf_ActiveWorldEntity();
11646
11647         surfaces = model->data_surfaces;
11648         update = model->brushq1.lightmapupdateflags;
11649
11650         // update light styles on this submodel
11651         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11652         {
11653                 model_brush_lightstyleinfo_t *style;
11654                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11655                 {
11656                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11657                         {
11658                                 int *list = style->surfacelist;
11659                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11660                                 for (j = 0;j < style->numsurfaces;j++)
11661                                         update[list[j]] = true;
11662                         }
11663                 }
11664         }
11665
11666         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11667
11668         if (debug)
11669         {
11670                 R_DrawDebugModel();
11671                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11672                 return;
11673         }
11674
11675         rsurface.lightmaptexture = NULL;
11676         rsurface.deluxemaptexture = NULL;
11677         rsurface.uselightmaptexture = false;
11678         rsurface.texture = NULL;
11679         rsurface.rtlight = NULL;
11680         numsurfacelist = 0;
11681         // add visible surfaces to draw list
11682         for (i = 0;i < model->nummodelsurfaces;i++)
11683         {
11684                 j = model->sortedmodelsurfaces[i];
11685                 if (r_refdef.viewcache.world_surfacevisible[j])
11686                         r_surfacelist[numsurfacelist++] = surfaces + j;
11687         }
11688         // update lightmaps if needed
11689         if (model->brushq1.firstrender)
11690         {
11691                 model->brushq1.firstrender = false;
11692                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11693                         if (update[j])
11694                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11695         }
11696         else if (update)
11697         {
11698                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11699                         if (r_refdef.viewcache.world_surfacevisible[j])
11700                                 if (update[j])
11701                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11702         }
11703         // don't do anything if there were no surfaces
11704         if (!numsurfacelist)
11705         {
11706                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11707                 return;
11708         }
11709         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11710
11711         // add to stats if desired
11712         if (r_speeds.integer && !skysurfaces && !depthonly)
11713         {
11714                 r_refdef.stats.world_surfaces += numsurfacelist;
11715                 for (j = 0;j < numsurfacelist;j++)
11716                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11717         }
11718
11719         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11720 }
11721
11722 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11723 {
11724         int i, j, endj, flagsmask;
11725         dp_model_t *model = ent->model;
11726         msurface_t *surfaces;
11727         unsigned char *update;
11728         int numsurfacelist = 0;
11729         if (model == NULL)
11730                 return;
11731
11732         if (r_maxsurfacelist < model->num_surfaces)
11733         {
11734                 r_maxsurfacelist = model->num_surfaces;
11735                 if (r_surfacelist)
11736                         Mem_Free((msurface_t **)r_surfacelist);
11737                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11738         }
11739
11740         // if the model is static it doesn't matter what value we give for
11741         // wantnormals and wanttangents, so this logic uses only rules applicable
11742         // to a model, knowing that they are meaningless otherwise
11743         if (ent == r_refdef.scene.worldentity)
11744                 RSurf_ActiveWorldEntity();
11745         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11746                 RSurf_ActiveModelEntity(ent, false, false, false);
11747         else if (prepass)
11748                 RSurf_ActiveModelEntity(ent, true, true, true);
11749         else if (depthonly)
11750         {
11751                 switch (vid.renderpath)
11752                 {
11753                 case RENDERPATH_GL20:
11754                 case RENDERPATH_D3D9:
11755                 case RENDERPATH_D3D10:
11756                 case RENDERPATH_D3D11:
11757                 case RENDERPATH_SOFT:
11758                 case RENDERPATH_GLES2:
11759                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11760                         break;
11761                 case RENDERPATH_GL11:
11762                 case RENDERPATH_GL13:
11763                 case RENDERPATH_GLES1:
11764                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11765                         break;
11766                 }
11767         }
11768         else
11769         {
11770                 switch (vid.renderpath)
11771                 {
11772                 case RENDERPATH_GL20:
11773                 case RENDERPATH_D3D9:
11774                 case RENDERPATH_D3D10:
11775                 case RENDERPATH_D3D11:
11776                 case RENDERPATH_SOFT:
11777                 case RENDERPATH_GLES2:
11778                         RSurf_ActiveModelEntity(ent, true, true, false);
11779                         break;
11780                 case RENDERPATH_GL11:
11781                 case RENDERPATH_GL13:
11782                 case RENDERPATH_GLES1:
11783                         RSurf_ActiveModelEntity(ent, true, false, false);
11784                         break;
11785                 }
11786         }
11787
11788         surfaces = model->data_surfaces;
11789         update = model->brushq1.lightmapupdateflags;
11790
11791         // update light styles
11792         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11793         {
11794                 model_brush_lightstyleinfo_t *style;
11795                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11796                 {
11797                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11798                         {
11799                                 int *list = style->surfacelist;
11800                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11801                                 for (j = 0;j < style->numsurfaces;j++)
11802                                         update[list[j]] = true;
11803                         }
11804                 }
11805         }
11806
11807         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11808
11809         if (debug)
11810         {
11811                 R_DrawDebugModel();
11812                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11813                 return;
11814         }
11815
11816         rsurface.lightmaptexture = NULL;
11817         rsurface.deluxemaptexture = NULL;
11818         rsurface.uselightmaptexture = false;
11819         rsurface.texture = NULL;
11820         rsurface.rtlight = NULL;
11821         numsurfacelist = 0;
11822         // add visible surfaces to draw list
11823         for (i = 0;i < model->nummodelsurfaces;i++)
11824                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11825         // don't do anything if there were no surfaces
11826         if (!numsurfacelist)
11827         {
11828                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11829                 return;
11830         }
11831         // update lightmaps if needed
11832         if (update)
11833         {
11834                 int updated = 0;
11835                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11836                 {
11837                         if (update[j])
11838                         {
11839                                 updated++;
11840                                 R_BuildLightMap(ent, surfaces + j);
11841                         }
11842                 }
11843         }
11844
11845         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11846
11847         // add to stats if desired
11848         if (r_speeds.integer && !skysurfaces && !depthonly)
11849         {
11850                 r_refdef.stats.entities_surfaces += numsurfacelist;
11851                 for (j = 0;j < numsurfacelist;j++)
11852                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11853         }
11854
11855         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11856 }
11857
11858 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11859 {
11860         static texture_t texture;
11861         static msurface_t surface;
11862         const msurface_t *surfacelist = &surface;
11863
11864         // fake enough texture and surface state to render this geometry
11865
11866         texture.update_lastrenderframe = -1; // regenerate this texture
11867         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11868         texture.currentskinframe = skinframe;
11869         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11870         texture.offsetmapping = OFFSETMAPPING_OFF;
11871         texture.offsetscale = 1;
11872         texture.specularscalemod = 1;
11873         texture.specularpowermod = 1;
11874
11875         surface.texture = &texture;
11876         surface.num_triangles = numtriangles;
11877         surface.num_firsttriangle = firsttriangle;
11878         surface.num_vertices = numvertices;
11879         surface.num_firstvertex = firstvertex;
11880
11881         // now render it
11882         rsurface.texture = R_GetCurrentTexture(surface.texture);
11883         rsurface.lightmaptexture = NULL;
11884         rsurface.deluxemaptexture = NULL;
11885         rsurface.uselightmaptexture = false;
11886         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11887 }
11888
11889 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)
11890 {
11891         static msurface_t surface;
11892         const msurface_t *surfacelist = &surface;
11893
11894         // fake enough texture and surface state to render this geometry
11895         surface.texture = texture;
11896         surface.num_triangles = numtriangles;
11897         surface.num_firsttriangle = firsttriangle;
11898         surface.num_vertices = numvertices;
11899         surface.num_firstvertex = firstvertex;
11900
11901         // now render it
11902         rsurface.texture = R_GetCurrentTexture(surface.texture);
11903         rsurface.lightmaptexture = NULL;
11904         rsurface.deluxemaptexture = NULL;
11905         rsurface.uselightmaptexture = false;
11906         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11907 }