]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
4b0ca40ce213bc50a1317bd5d0e1034845556254
[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"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
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_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
124 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"};
125 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"};
126 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
127 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
128 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
129 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
130 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
131 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"};
132 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
133 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
134 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
135
136 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
137 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
138 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
139 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
140 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
141 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
142 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
143 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
144
145 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)"};
146 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"};
147
148 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
149 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
150 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
151
152 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"};
153 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"};
154 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"};
155 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
156 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
157 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"};
158 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)"};
159 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)"};
160 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
161
162 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)"};
163 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
164 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)"};
165 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
166 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)"};
167 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)"};
168 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
169 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"};
170 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."};
171 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
176 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)"};
177 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)"};
178 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)"};
179 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)"};
180
181 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)"};
182 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
183 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"};
184 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
185 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
186 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
187 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"};
188 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"};
189 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)"};
190
191 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
192 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
193 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
194 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
195
196 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
197 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
198
199 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
200 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
201 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
202 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
203 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
204
205 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
206 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
207 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
208 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
209 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
210 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
211 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
212 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
213 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
214 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
215
216 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"};
217
218 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"};
219
220 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
221
222 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
223
224 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
225 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"};
226
227 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."};
228
229 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)"};
230
231 extern cvar_t v_glslgamma;
232 extern cvar_t v_glslgamma_2d;
233
234 extern qboolean v_flipped_state;
235
236 r_framebufferstate_t r_fb;
237
238 /// shadow volume bsp struct with automatically growing nodes buffer
239 svbsp_t r_svbsp;
240
241 rtexture_t *r_texture_blanknormalmap;
242 rtexture_t *r_texture_white;
243 rtexture_t *r_texture_grey128;
244 rtexture_t *r_texture_black;
245 rtexture_t *r_texture_notexture;
246 rtexture_t *r_texture_whitecube;
247 rtexture_t *r_texture_normalizationcube;
248 rtexture_t *r_texture_fogattenuation;
249 rtexture_t *r_texture_fogheighttexture;
250 rtexture_t *r_texture_gammaramps;
251 unsigned int r_texture_gammaramps_serial;
252 //rtexture_t *r_texture_fogintensity;
253 rtexture_t *r_texture_reflectcube;
254
255 // TODO: hash lookups?
256 typedef struct cubemapinfo_s
257 {
258         char basename[64];
259         rtexture_t *texture;
260 }
261 cubemapinfo_t;
262
263 int r_texture_numcubemaps;
264 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
265
266 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
267 unsigned int r_numqueries;
268 unsigned int r_maxqueries;
269
270 typedef struct r_qwskincache_s
271 {
272         char name[MAX_QPATH];
273         skinframe_t *skinframe;
274 }
275 r_qwskincache_t;
276
277 static r_qwskincache_t *r_qwskincache;
278 static int r_qwskincache_size;
279
280 /// vertex coordinates for a quad that covers the screen exactly
281 extern const float r_screenvertex3f[12];
282 extern const float r_d3dscreenvertex3f[12];
283 const float r_screenvertex3f[12] =
284 {
285         0, 0, 0,
286         1, 0, 0,
287         1, 1, 0,
288         0, 1, 0
289 };
290 const float r_d3dscreenvertex3f[12] =
291 {
292         0, 1, 0,
293         1, 1, 0,
294         1, 0, 0,
295         0, 0, 0
296 };
297
298 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
299 {
300         int i;
301         for (i = 0;i < verts;i++)
302         {
303                 out[0] = in[0] * r;
304                 out[1] = in[1] * g;
305                 out[2] = in[2] * b;
306                 out[3] = in[3];
307                 in += 4;
308                 out += 4;
309         }
310 }
311
312 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
313 {
314         int i;
315         for (i = 0;i < verts;i++)
316         {
317                 out[0] = r;
318                 out[1] = g;
319                 out[2] = b;
320                 out[3] = a;
321                 out += 4;
322         }
323 }
324
325 // FIXME: move this to client?
326 void FOG_clear(void)
327 {
328         if (gamemode == GAME_NEHAHRA)
329         {
330                 Cvar_Set("gl_fogenable", "0");
331                 Cvar_Set("gl_fogdensity", "0.2");
332                 Cvar_Set("gl_fogred", "0.3");
333                 Cvar_Set("gl_foggreen", "0.3");
334                 Cvar_Set("gl_fogblue", "0.3");
335         }
336         r_refdef.fog_density = 0;
337         r_refdef.fog_red = 0;
338         r_refdef.fog_green = 0;
339         r_refdef.fog_blue = 0;
340         r_refdef.fog_alpha = 1;
341         r_refdef.fog_start = 0;
342         r_refdef.fog_end = 16384;
343         r_refdef.fog_height = 1<<30;
344         r_refdef.fog_fadedepth = 128;
345         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
346 }
347
348 static void R_BuildBlankTextures(void)
349 {
350         unsigned char data[4];
351         data[2] = 128; // normal X
352         data[1] = 128; // normal Y
353         data[0] = 255; // normal Z
354         data[3] = 255; // height
355         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
356         data[0] = 255;
357         data[1] = 255;
358         data[2] = 255;
359         data[3] = 255;
360         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
361         data[0] = 128;
362         data[1] = 128;
363         data[2] = 128;
364         data[3] = 255;
365         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
366         data[0] = 0;
367         data[1] = 0;
368         data[2] = 0;
369         data[3] = 255;
370         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
371 }
372
373 static void R_BuildNoTexture(void)
374 {
375         int x, y;
376         unsigned char pix[16][16][4];
377         // this makes a light grey/dark grey checkerboard texture
378         for (y = 0;y < 16;y++)
379         {
380                 for (x = 0;x < 16;x++)
381                 {
382                         if ((y < 8) ^ (x < 8))
383                         {
384                                 pix[y][x][0] = 128;
385                                 pix[y][x][1] = 128;
386                                 pix[y][x][2] = 128;
387                                 pix[y][x][3] = 255;
388                         }
389                         else
390                         {
391                                 pix[y][x][0] = 64;
392                                 pix[y][x][1] = 64;
393                                 pix[y][x][2] = 64;
394                                 pix[y][x][3] = 255;
395                         }
396                 }
397         }
398         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
399 }
400
401 static void R_BuildWhiteCube(void)
402 {
403         unsigned char data[6*1*1*4];
404         memset(data, 255, sizeof(data));
405         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
406 }
407
408 static void R_BuildNormalizationCube(void)
409 {
410         int x, y, side;
411         vec3_t v;
412         vec_t s, t, intensity;
413 #define NORMSIZE 64
414         unsigned char *data;
415         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
416         for (side = 0;side < 6;side++)
417         {
418                 for (y = 0;y < NORMSIZE;y++)
419                 {
420                         for (x = 0;x < NORMSIZE;x++)
421                         {
422                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
423                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
424                                 switch(side)
425                                 {
426                                 default:
427                                 case 0:
428                                         v[0] = 1;
429                                         v[1] = -t;
430                                         v[2] = -s;
431                                         break;
432                                 case 1:
433                                         v[0] = -1;
434                                         v[1] = -t;
435                                         v[2] = s;
436                                         break;
437                                 case 2:
438                                         v[0] = s;
439                                         v[1] = 1;
440                                         v[2] = t;
441                                         break;
442                                 case 3:
443                                         v[0] = s;
444                                         v[1] = -1;
445                                         v[2] = -t;
446                                         break;
447                                 case 4:
448                                         v[0] = s;
449                                         v[1] = -t;
450                                         v[2] = 1;
451                                         break;
452                                 case 5:
453                                         v[0] = -s;
454                                         v[1] = -t;
455                                         v[2] = -1;
456                                         break;
457                                 }
458                                 intensity = 127.0f / sqrt(DotProduct(v, v));
459                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
460                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
461                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
462                                 data[((side*64+y)*64+x)*4+3] = 255;
463                         }
464                 }
465         }
466         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
467         Mem_Free(data);
468 }
469
470 static void R_BuildFogTexture(void)
471 {
472         int x, b;
473 #define FOGWIDTH 256
474         unsigned char data1[FOGWIDTH][4];
475         //unsigned char data2[FOGWIDTH][4];
476         double d, r, alpha;
477
478         r_refdef.fogmasktable_start = r_refdef.fog_start;
479         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
480         r_refdef.fogmasktable_range = r_refdef.fogrange;
481         r_refdef.fogmasktable_density = r_refdef.fog_density;
482
483         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
484         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
485         {
486                 d = (x * r - r_refdef.fogmasktable_start);
487                 if(developer_extra.integer)
488                         Con_DPrintf("%f ", d);
489                 d = max(0, d);
490                 if (r_fog_exp2.integer)
491                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
492                 else
493                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
494                 if(developer_extra.integer)
495                         Con_DPrintf(" : %f ", alpha);
496                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
497                 if(developer_extra.integer)
498                         Con_DPrintf(" = %f\n", alpha);
499                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
500         }
501
502         for (x = 0;x < FOGWIDTH;x++)
503         {
504                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
505                 data1[x][0] = b;
506                 data1[x][1] = b;
507                 data1[x][2] = b;
508                 data1[x][3] = 255;
509                 //data2[x][0] = 255 - b;
510                 //data2[x][1] = 255 - b;
511                 //data2[x][2] = 255 - b;
512                 //data2[x][3] = 255;
513         }
514         if (r_texture_fogattenuation)
515         {
516                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
517                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
518         }
519         else
520         {
521                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
522                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
523         }
524 }
525
526 static void R_BuildFogHeightTexture(void)
527 {
528         unsigned char *inpixels;
529         int size;
530         int x;
531         int y;
532         int j;
533         float c[4];
534         float f;
535         inpixels = NULL;
536         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
537         if (r_refdef.fogheighttexturename[0])
538                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
539         if (!inpixels)
540         {
541                 r_refdef.fog_height_tablesize = 0;
542                 if (r_texture_fogheighttexture)
543                         R_FreeTexture(r_texture_fogheighttexture);
544                 r_texture_fogheighttexture = NULL;
545                 if (r_refdef.fog_height_table2d)
546                         Mem_Free(r_refdef.fog_height_table2d);
547                 r_refdef.fog_height_table2d = NULL;
548                 if (r_refdef.fog_height_table1d)
549                         Mem_Free(r_refdef.fog_height_table1d);
550                 r_refdef.fog_height_table1d = NULL;
551                 return;
552         }
553         size = image_width;
554         r_refdef.fog_height_tablesize = size;
555         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
556         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
557         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
558         Mem_Free(inpixels);
559         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
560         // average fog color table accounting for every fog layer between a point
561         // and the camera.  (Note: attenuation is handled separately!)
562         for (y = 0;y < size;y++)
563         {
564                 for (x = 0;x < size;x++)
565                 {
566                         Vector4Clear(c);
567                         f = 0;
568                         if (x < y)
569                         {
570                                 for (j = x;j <= y;j++)
571                                 {
572                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
573                                         f++;
574                                 }
575                         }
576                         else
577                         {
578                                 for (j = x;j >= y;j--)
579                                 {
580                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
581                                         f++;
582                                 }
583                         }
584                         f = 1.0f / f;
585                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
586                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
587                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
588                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
589                 }
590         }
591         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
592 }
593
594 //=======================================================================================================================================================
595
596 static const char *builtinshaderstring =
597 #include "shader_glsl.h"
598 ;
599
600 const char *builtinhlslshaderstring =
601 #include "shader_hlsl.h"
602 ;
603
604 char *glslshaderstring = NULL;
605 char *hlslshaderstring = NULL;
606
607 //=======================================================================================================================================================
608
609 typedef struct shaderpermutationinfo_s
610 {
611         const char *pretext;
612         const char *name;
613 }
614 shaderpermutationinfo_t;
615
616 typedef struct shadermodeinfo_s
617 {
618         const char *vertexfilename;
619         const char *geometryfilename;
620         const char *fragmentfilename;
621         const char *pretext;
622         const char *name;
623 }
624 shadermodeinfo_t;
625
626 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
627 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
628 {
629         {"#define USEDIFFUSE\n", " diffuse"},
630         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
631         {"#define USEVIEWTINT\n", " viewtint"},
632         {"#define USECOLORMAPPING\n", " colormapping"},
633         {"#define USESATURATION\n", " saturation"},
634         {"#define USEFOGINSIDE\n", " foginside"},
635         {"#define USEFOGOUTSIDE\n", " fogoutside"},
636         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
637         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
638         {"#define USEGAMMARAMPS\n", " gammaramps"},
639         {"#define USECUBEFILTER\n", " cubefilter"},
640         {"#define USEGLOW\n", " glow"},
641         {"#define USEBLOOM\n", " bloom"},
642         {"#define USESPECULAR\n", " specular"},
643         {"#define USEPOSTPROCESSING\n", " postprocessing"},
644         {"#define USEREFLECTION\n", " reflection"},
645         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
646         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
647         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
648         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
649         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
650         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
651         {"#define USEALPHAKILL\n", " alphakill"},
652         {"#define USEREFLECTCUBE\n", " reflectcube"},
653         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
654         {"#define USEBOUNCEGRID\n", " bouncegrid"},
655         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
656         {"#define USETRIPPY\n", " trippy"},
657         {"#define USEDEPTHRGB\n", " depthrgb"},
658         {"#define USEALPHAGENVERTEX\n", "alphagenvertex"}
659 };
660
661 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
662 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
663 {
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
682 };
683
684 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
685 {
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 };
705
706 struct r_glsl_permutation_s;
707 typedef struct r_glsl_permutation_s
708 {
709         /// hash lookup data
710         struct r_glsl_permutation_s *hashnext;
711         unsigned int mode;
712         unsigned int permutation;
713
714         /// indicates if we have tried compiling this permutation already
715         qboolean compiled;
716         /// 0 if compilation failed
717         int program;
718         // texture units assigned to each detected uniform
719         int tex_Texture_First;
720         int tex_Texture_Second;
721         int tex_Texture_GammaRamps;
722         int tex_Texture_Normal;
723         int tex_Texture_Color;
724         int tex_Texture_Gloss;
725         int tex_Texture_Glow;
726         int tex_Texture_SecondaryNormal;
727         int tex_Texture_SecondaryColor;
728         int tex_Texture_SecondaryGloss;
729         int tex_Texture_SecondaryGlow;
730         int tex_Texture_Pants;
731         int tex_Texture_Shirt;
732         int tex_Texture_FogHeightTexture;
733         int tex_Texture_FogMask;
734         int tex_Texture_Lightmap;
735         int tex_Texture_Deluxemap;
736         int tex_Texture_Attenuation;
737         int tex_Texture_Cube;
738         int tex_Texture_Refraction;
739         int tex_Texture_Reflection;
740         int tex_Texture_ShadowMap2D;
741         int tex_Texture_CubeProjection;
742         int tex_Texture_ScreenNormalMap;
743         int tex_Texture_ScreenDiffuse;
744         int tex_Texture_ScreenSpecular;
745         int tex_Texture_ReflectMask;
746         int tex_Texture_ReflectCube;
747         int tex_Texture_BounceGrid;
748         /// locations of detected uniforms in program object, or -1 if not found
749         int loc_Texture_First;
750         int loc_Texture_Second;
751         int loc_Texture_GammaRamps;
752         int loc_Texture_Normal;
753         int loc_Texture_Color;
754         int loc_Texture_Gloss;
755         int loc_Texture_Glow;
756         int loc_Texture_SecondaryNormal;
757         int loc_Texture_SecondaryColor;
758         int loc_Texture_SecondaryGloss;
759         int loc_Texture_SecondaryGlow;
760         int loc_Texture_Pants;
761         int loc_Texture_Shirt;
762         int loc_Texture_FogHeightTexture;
763         int loc_Texture_FogMask;
764         int loc_Texture_Lightmap;
765         int loc_Texture_Deluxemap;
766         int loc_Texture_Attenuation;
767         int loc_Texture_Cube;
768         int loc_Texture_Refraction;
769         int loc_Texture_Reflection;
770         int loc_Texture_ShadowMap2D;
771         int loc_Texture_CubeProjection;
772         int loc_Texture_ScreenNormalMap;
773         int loc_Texture_ScreenDiffuse;
774         int loc_Texture_ScreenSpecular;
775         int loc_Texture_ReflectMask;
776         int loc_Texture_ReflectCube;
777         int loc_Texture_BounceGrid;
778         int loc_Alpha;
779         int loc_BloomBlur_Parameters;
780         int loc_ClientTime;
781         int loc_Color_Ambient;
782         int loc_Color_Diffuse;
783         int loc_Color_Specular;
784         int loc_Color_Glow;
785         int loc_Color_Pants;
786         int loc_Color_Shirt;
787         int loc_DeferredColor_Ambient;
788         int loc_DeferredColor_Diffuse;
789         int loc_DeferredColor_Specular;
790         int loc_DeferredMod_Diffuse;
791         int loc_DeferredMod_Specular;
792         int loc_DistortScaleRefractReflect;
793         int loc_EyePosition;
794         int loc_FogColor;
795         int loc_FogHeightFade;
796         int loc_FogPlane;
797         int loc_FogPlaneViewDist;
798         int loc_FogRangeRecip;
799         int loc_LightColor;
800         int loc_LightDir;
801         int loc_LightPosition;
802         int loc_OffsetMapping_ScaleSteps;
803         int loc_OffsetMapping_LodDistance;
804         int loc_OffsetMapping_Bias;
805         int loc_PixelSize;
806         int loc_ReflectColor;
807         int loc_ReflectFactor;
808         int loc_ReflectOffset;
809         int loc_RefractColor;
810         int loc_Saturation;
811         int loc_ScreenCenterRefractReflect;
812         int loc_ScreenScaleRefractReflect;
813         int loc_ScreenToDepth;
814         int loc_ShadowMap_Parameters;
815         int loc_ShadowMap_TextureScale;
816         int loc_SpecularPower;
817         int loc_UserVec1;
818         int loc_UserVec2;
819         int loc_UserVec3;
820         int loc_UserVec4;
821         int loc_ViewTintColor;
822         int loc_ViewToLight;
823         int loc_ModelToLight;
824         int loc_TexMatrix;
825         int loc_BackgroundTexMatrix;
826         int loc_ModelViewProjectionMatrix;
827         int loc_ModelViewMatrix;
828         int loc_PixelToScreenTexCoord;
829         int loc_ModelToReflectCube;
830         int loc_ShadowMapMatrix;
831         int loc_BloomColorSubtract;
832         int loc_NormalmapScrollBlend;
833         int loc_BounceGridMatrix;
834         int loc_BounceGridIntensity;
835 }
836 r_glsl_permutation_t;
837
838 #define SHADERPERMUTATION_HASHSIZE 256
839
840
841 // non-degradable "lightweight" shader parameters to keep the permutations simpler
842 // these can NOT degrade! only use for simple stuff
843 enum
844 {
845         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
846         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
847         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
849         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
850         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
851         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
852         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
853         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
854         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
855         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
856 };
857 #define SHADERSTATICPARMS_COUNT 11
858
859 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
860 static int shaderstaticparms_count = 0;
861
862 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
863 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
864
865 extern qboolean r_shadow_shadowmapsampler;
866 extern int r_shadow_shadowmappcf;
867 qboolean R_CompileShader_CheckStaticParms(void)
868 {
869         static int r_compileshader_staticparms_save[1];
870         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
871         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
872
873         // detect all
874         if (r_glsl_saturation_redcompensate.integer)
875                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
876         if (r_glsl_vertextextureblend_usebothalphas.integer)
877                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
878         if (r_shadow_glossexact.integer)
879                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
880         if (r_glsl_postprocess.integer)
881         {
882                 if (r_glsl_postprocess_uservec1_enable.integer)
883                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
884                 if (r_glsl_postprocess_uservec2_enable.integer)
885                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
886                 if (r_glsl_postprocess_uservec3_enable.integer)
887                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
888                 if (r_glsl_postprocess_uservec4_enable.integer)
889                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
890         }
891         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
892                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
893
894         if (r_shadow_shadowmapsampler)
895                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
896         if (r_shadow_shadowmappcf > 1)
897                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
898         else if (r_shadow_shadowmappcf)
899                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
900
901         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
902 }
903
904 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
905         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
906                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
907         else \
908                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
909 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
910 {
911         shaderstaticparms_count = 0;
912
913         // emit all
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
925 }
926
927 /// information about each possible shader permutation
928 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
929 /// currently selected permutation
930 r_glsl_permutation_t *r_glsl_permutation;
931 /// storage for permutations linked in the hash table
932 memexpandablearray_t r_glsl_permutationarray;
933
934 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
935 {
936         //unsigned int hashdepth = 0;
937         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
938         r_glsl_permutation_t *p;
939         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
940         {
941                 if (p->mode == mode && p->permutation == permutation)
942                 {
943                         //if (hashdepth > 10)
944                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
945                         return p;
946                 }
947                 //hashdepth++;
948         }
949         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
950         p->mode = mode;
951         p->permutation = permutation;
952         p->hashnext = r_glsl_permutationhash[mode][hashindex];
953         r_glsl_permutationhash[mode][hashindex] = p;
954         //if (hashdepth > 10)
955         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
956         return p;
957 }
958
959 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
960 {
961         char *shaderstring;
962         if (!filename || !filename[0])
963                 return NULL;
964         if (!strcmp(filename, "glsl/default.glsl"))
965         {
966                 if (!glslshaderstring)
967                 {
968                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
969                         if (glslshaderstring)
970                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
971                         else
972                                 glslshaderstring = (char *)builtinshaderstring;
973                 }
974                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
975                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
976                 return shaderstring;
977         }
978         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
979         if (shaderstring)
980         {
981                 if (printfromdisknotice)
982                         Con_DPrintf("from disk %s... ", filename);
983                 return shaderstring;
984         }
985         return shaderstring;
986 }
987
988 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
989 {
990         int i;
991         int sampler;
992         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
993         char *vertexstring, *geometrystring, *fragmentstring;
994         char permutationname[256];
995         int vertstrings_count = 0;
996         int geomstrings_count = 0;
997         int fragstrings_count = 0;
998         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
999         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1000         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1001
1002         if (p->compiled)
1003                 return;
1004         p->compiled = true;
1005         p->program = 0;
1006
1007         permutationname[0] = 0;
1008         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1009         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1010         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1011
1012         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1013
1014         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1015         if(vid.support.gl20shaders130)
1016         {
1017                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1018                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1019                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1020                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1021                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1022                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1023         }
1024
1025         // the first pretext is which type of shader to compile as
1026         // (later these will all be bound together as a program object)
1027         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1028         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1029         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1030
1031         // the second pretext is the mode (for example a light source)
1032         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1033         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1034         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1035         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1036
1037         // now add all the permutation pretexts
1038         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1039         {
1040                 if (permutation & (1<<i))
1041                 {
1042                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1043                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1044                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1045                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1046                 }
1047                 else
1048                 {
1049                         // keep line numbers correct
1050                         vertstrings_list[vertstrings_count++] = "\n";
1051                         geomstrings_list[geomstrings_count++] = "\n";
1052                         fragstrings_list[fragstrings_count++] = "\n";
1053                 }
1054         }
1055
1056         // add static parms
1057         R_CompileShader_AddStaticParms(mode, permutation);
1058         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1059         vertstrings_count += shaderstaticparms_count;
1060         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1061         geomstrings_count += shaderstaticparms_count;
1062         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1063         fragstrings_count += shaderstaticparms_count;
1064
1065         // now append the shader text itself
1066         vertstrings_list[vertstrings_count++] = vertexstring;
1067         geomstrings_list[geomstrings_count++] = geometrystring;
1068         fragstrings_list[fragstrings_count++] = fragmentstring;
1069
1070         // if any sources were NULL, clear the respective list
1071         if (!vertexstring)
1072                 vertstrings_count = 0;
1073         if (!geometrystring)
1074                 geomstrings_count = 0;
1075         if (!fragmentstring)
1076                 fragstrings_count = 0;
1077
1078         // compile the shader program
1079         if (vertstrings_count + geomstrings_count + fragstrings_count)
1080                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1081         if (p->program)
1082         {
1083                 CHECKGLERROR
1084                 qglUseProgram(p->program);CHECKGLERROR
1085                 // look up all the uniform variable names we care about, so we don't
1086                 // have to look them up every time we set them
1087
1088                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1089                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1090                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1091                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1092                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1093                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1094                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1095                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1096                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1097                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1098                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1099                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1100                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1101                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1102                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1103                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1104                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1105                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1106                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1107                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1108                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1109                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1110                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1111                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1112                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1113                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1114                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1115                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1116                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1117                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1118                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1119                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1120                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1121                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1122                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1123                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1124                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1125                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1126                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1127                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1128                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1129                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1130                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1131                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1132                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1133                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1134                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1135                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1136                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1137                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1138                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1139                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1140                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1141                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1142                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1143                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1144                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1145                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1146                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1147                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1148                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1149                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1150                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1151                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1152                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1153                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1154                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1155                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1156                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1157                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1158                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1159                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1160                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1161                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1162                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1163                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1164                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1165                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1166                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1167                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1168                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1169                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1170                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1171                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1172                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1173                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1174                 // initialize the samplers to refer to the texture units we use
1175                 p->tex_Texture_First = -1;
1176                 p->tex_Texture_Second = -1;
1177                 p->tex_Texture_GammaRamps = -1;
1178                 p->tex_Texture_Normal = -1;
1179                 p->tex_Texture_Color = -1;
1180                 p->tex_Texture_Gloss = -1;
1181                 p->tex_Texture_Glow = -1;
1182                 p->tex_Texture_SecondaryNormal = -1;
1183                 p->tex_Texture_SecondaryColor = -1;
1184                 p->tex_Texture_SecondaryGloss = -1;
1185                 p->tex_Texture_SecondaryGlow = -1;
1186                 p->tex_Texture_Pants = -1;
1187                 p->tex_Texture_Shirt = -1;
1188                 p->tex_Texture_FogHeightTexture = -1;
1189                 p->tex_Texture_FogMask = -1;
1190                 p->tex_Texture_Lightmap = -1;
1191                 p->tex_Texture_Deluxemap = -1;
1192                 p->tex_Texture_Attenuation = -1;
1193                 p->tex_Texture_Cube = -1;
1194                 p->tex_Texture_Refraction = -1;
1195                 p->tex_Texture_Reflection = -1;
1196                 p->tex_Texture_ShadowMap2D = -1;
1197                 p->tex_Texture_CubeProjection = -1;
1198                 p->tex_Texture_ScreenNormalMap = -1;
1199                 p->tex_Texture_ScreenDiffuse = -1;
1200                 p->tex_Texture_ScreenSpecular = -1;
1201                 p->tex_Texture_ReflectMask = -1;
1202                 p->tex_Texture_ReflectCube = -1;
1203                 p->tex_Texture_BounceGrid = -1;
1204                 sampler = 0;
1205                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1206                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1207                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1208                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1209                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1210                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1211                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1212                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1213                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1214                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1215                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1216                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1217                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1218                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1219                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1220                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1221                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1222                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1223                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1224                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1225                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1226                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1227                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1228                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1229                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1230                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1231                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1232                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1233                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1234                 CHECKGLERROR
1235                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1236         }
1237         else
1238                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1239
1240         // free the strings
1241         if (vertexstring)
1242                 Mem_Free(vertexstring);
1243         if (geometrystring)
1244                 Mem_Free(geometrystring);
1245         if (fragmentstring)
1246                 Mem_Free(fragmentstring);
1247 }
1248
1249 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1250 {
1251         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1252         if (r_glsl_permutation != perm)
1253         {
1254                 r_glsl_permutation = perm;
1255                 if (!r_glsl_permutation->program)
1256                 {
1257                         if (!r_glsl_permutation->compiled)
1258                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1259                         if (!r_glsl_permutation->program)
1260                         {
1261                                 // remove features until we find a valid permutation
1262                                 int i;
1263                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1264                                 {
1265                                         // reduce i more quickly whenever it would not remove any bits
1266                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1267                                         if (!(permutation & j))
1268                                                 continue;
1269                                         permutation -= j;
1270                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1271                                         if (!r_glsl_permutation->compiled)
1272                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1273                                         if (r_glsl_permutation->program)
1274                                                 break;
1275                                 }
1276                                 if (i >= SHADERPERMUTATION_COUNT)
1277                                 {
1278                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1279                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1280                                         qglUseProgram(0);CHECKGLERROR
1281                                         return; // no bit left to clear, entire mode is broken
1282                                 }
1283                         }
1284                 }
1285                 CHECKGLERROR
1286                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1287         }
1288         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1289         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1290         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1291 }
1292
1293 #ifdef SUPPORTD3D
1294
1295 #ifdef SUPPORTD3D
1296 #include <d3d9.h>
1297 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1298 extern D3DCAPS9 vid_d3d9caps;
1299 #endif
1300
1301 struct r_hlsl_permutation_s;
1302 typedef struct r_hlsl_permutation_s
1303 {
1304         /// hash lookup data
1305         struct r_hlsl_permutation_s *hashnext;
1306         unsigned int mode;
1307         unsigned int permutation;
1308
1309         /// indicates if we have tried compiling this permutation already
1310         qboolean compiled;
1311         /// NULL if compilation failed
1312         IDirect3DVertexShader9 *vertexshader;
1313         IDirect3DPixelShader9 *pixelshader;
1314 }
1315 r_hlsl_permutation_t;
1316
1317 typedef enum D3DVSREGISTER_e
1318 {
1319         D3DVSREGISTER_TexMatrix = 0, // float4x4
1320         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1321         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1322         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1323         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1324         D3DVSREGISTER_ModelToLight = 20, // float4x4
1325         D3DVSREGISTER_EyePosition = 24,
1326         D3DVSREGISTER_FogPlane = 25,
1327         D3DVSREGISTER_LightDir = 26,
1328         D3DVSREGISTER_LightPosition = 27,
1329 }
1330 D3DVSREGISTER_t;
1331
1332 typedef enum D3DPSREGISTER_e
1333 {
1334         D3DPSREGISTER_Alpha = 0,
1335         D3DPSREGISTER_BloomBlur_Parameters = 1,
1336         D3DPSREGISTER_ClientTime = 2,
1337         D3DPSREGISTER_Color_Ambient = 3,
1338         D3DPSREGISTER_Color_Diffuse = 4,
1339         D3DPSREGISTER_Color_Specular = 5,
1340         D3DPSREGISTER_Color_Glow = 6,
1341         D3DPSREGISTER_Color_Pants = 7,
1342         D3DPSREGISTER_Color_Shirt = 8,
1343         D3DPSREGISTER_DeferredColor_Ambient = 9,
1344         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1345         D3DPSREGISTER_DeferredColor_Specular = 11,
1346         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1347         D3DPSREGISTER_DeferredMod_Specular = 13,
1348         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1349         D3DPSREGISTER_EyePosition = 15, // unused
1350         D3DPSREGISTER_FogColor = 16,
1351         D3DPSREGISTER_FogHeightFade = 17,
1352         D3DPSREGISTER_FogPlane = 18,
1353         D3DPSREGISTER_FogPlaneViewDist = 19,
1354         D3DPSREGISTER_FogRangeRecip = 20,
1355         D3DPSREGISTER_LightColor = 21,
1356         D3DPSREGISTER_LightDir = 22, // unused
1357         D3DPSREGISTER_LightPosition = 23,
1358         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1359         D3DPSREGISTER_PixelSize = 25,
1360         D3DPSREGISTER_ReflectColor = 26,
1361         D3DPSREGISTER_ReflectFactor = 27,
1362         D3DPSREGISTER_ReflectOffset = 28,
1363         D3DPSREGISTER_RefractColor = 29,
1364         D3DPSREGISTER_Saturation = 30,
1365         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1366         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1367         D3DPSREGISTER_ScreenToDepth = 33,
1368         D3DPSREGISTER_ShadowMap_Parameters = 34,
1369         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1370         D3DPSREGISTER_SpecularPower = 36,
1371         D3DPSREGISTER_UserVec1 = 37,
1372         D3DPSREGISTER_UserVec2 = 38,
1373         D3DPSREGISTER_UserVec3 = 39,
1374         D3DPSREGISTER_UserVec4 = 40,
1375         D3DPSREGISTER_ViewTintColor = 41,
1376         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1377         D3DPSREGISTER_BloomColorSubtract = 43,
1378         D3DPSREGISTER_ViewToLight = 44, // float4x4
1379         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1380         D3DPSREGISTER_NormalmapScrollBlend = 52,
1381         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1382         D3DPSREGISTER_OffsetMapping_Bias = 54,
1383         // next at 54
1384 }
1385 D3DPSREGISTER_t;
1386
1387 /// information about each possible shader permutation
1388 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1389 /// currently selected permutation
1390 r_hlsl_permutation_t *r_hlsl_permutation;
1391 /// storage for permutations linked in the hash table
1392 memexpandablearray_t r_hlsl_permutationarray;
1393
1394 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1395 {
1396         //unsigned int hashdepth = 0;
1397         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1398         r_hlsl_permutation_t *p;
1399         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1400         {
1401                 if (p->mode == mode && p->permutation == permutation)
1402                 {
1403                         //if (hashdepth > 10)
1404                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1405                         return p;
1406                 }
1407                 //hashdepth++;
1408         }
1409         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1410         p->mode = mode;
1411         p->permutation = permutation;
1412         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1413         r_hlsl_permutationhash[mode][hashindex] = p;
1414         //if (hashdepth > 10)
1415         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1416         return p;
1417 }
1418
1419 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1420 {
1421         char *shaderstring;
1422         if (!filename || !filename[0])
1423                 return NULL;
1424         if (!strcmp(filename, "hlsl/default.hlsl"))
1425         {
1426                 if (!hlslshaderstring)
1427                 {
1428                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1429                         if (hlslshaderstring)
1430                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1431                         else
1432                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1433                 }
1434                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1435                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1436                 return shaderstring;
1437         }
1438         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1439         if (shaderstring)
1440         {
1441                 if (printfromdisknotice)
1442                         Con_DPrintf("from disk %s... ", filename);
1443                 return shaderstring;
1444         }
1445         return shaderstring;
1446 }
1447
1448 #include <d3dx9.h>
1449 //#include <d3dx9shader.h>
1450 //#include <d3dx9mesh.h>
1451
1452 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1453 {
1454         DWORD *vsbin = NULL;
1455         DWORD *psbin = NULL;
1456         fs_offset_t vsbinsize;
1457         fs_offset_t psbinsize;
1458 //      IDirect3DVertexShader9 *vs = NULL;
1459 //      IDirect3DPixelShader9 *ps = NULL;
1460         ID3DXBuffer *vslog = NULL;
1461         ID3DXBuffer *vsbuffer = NULL;
1462         ID3DXConstantTable *vsconstanttable = NULL;
1463         ID3DXBuffer *pslog = NULL;
1464         ID3DXBuffer *psbuffer = NULL;
1465         ID3DXConstantTable *psconstanttable = NULL;
1466         int vsresult = 0;
1467         int psresult = 0;
1468         char temp[MAX_INPUTLINE];
1469         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1470         char vabuf[1024];
1471         qboolean debugshader = gl_paranoid.integer != 0;
1472         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1473         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1474         if (!debugshader)
1475         {
1476                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1477                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1478         }
1479         if ((!vsbin && vertstring) || (!psbin && fragstring))
1480         {
1481                 const char* dllnames_d3dx9 [] =
1482                 {
1483                         "d3dx9_43.dll",
1484                         "d3dx9_42.dll",
1485                         "d3dx9_41.dll",
1486                         "d3dx9_40.dll",
1487                         "d3dx9_39.dll",
1488                         "d3dx9_38.dll",
1489                         "d3dx9_37.dll",
1490                         "d3dx9_36.dll",
1491                         "d3dx9_35.dll",
1492                         "d3dx9_34.dll",
1493                         "d3dx9_33.dll",
1494                         "d3dx9_32.dll",
1495                         "d3dx9_31.dll",
1496                         "d3dx9_30.dll",
1497                         "d3dx9_29.dll",
1498                         "d3dx9_28.dll",
1499                         "d3dx9_27.dll",
1500                         "d3dx9_26.dll",
1501                         "d3dx9_25.dll",
1502                         "d3dx9_24.dll",
1503                         NULL
1504                 };
1505                 dllhandle_t d3dx9_dll = NULL;
1506                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1507                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1508                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1509                 dllfunction_t d3dx9_dllfuncs[] =
1510                 {
1511                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1512                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1513                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1514                         {NULL, NULL}
1515                 };
1516                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1517                 {
1518                         DWORD shaderflags = 0;
1519                         if (debugshader)
1520                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1521                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1522                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1523                         if (vertstring && vertstring[0])
1524                         {
1525                                 if (debugshader)
1526                                 {
1527 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1528 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1529                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1530                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1531                                 }
1532                                 else
1533                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1534                                 if (vsbuffer)
1535                                 {
1536                                         vsbinsize = vsbuffer->GetBufferSize();
1537                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1538                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1539                                         vsbuffer->Release();
1540                                 }
1541                                 if (vslog)
1542                                 {
1543                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1544                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1545                                         vslog->Release();
1546                                 }
1547                         }
1548                         if (fragstring && fragstring[0])
1549                         {
1550                                 if (debugshader)
1551                                 {
1552 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1553 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1554                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1555                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1556                                 }
1557                                 else
1558                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1559                                 if (psbuffer)
1560                                 {
1561                                         psbinsize = psbuffer->GetBufferSize();
1562                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1563                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1564                                         psbuffer->Release();
1565                                 }
1566                                 if (pslog)
1567                                 {
1568                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1569                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1570                                         pslog->Release();
1571                                 }
1572                         }
1573                         Sys_UnloadLibrary(&d3dx9_dll);
1574                 }
1575                 else
1576                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1577         }
1578         if (vsbin && psbin)
1579         {
1580                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1581                 if (FAILED(vsresult))
1582                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1583                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1584                 if (FAILED(psresult))
1585                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1586         }
1587         // free the shader data
1588         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1589         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1590 }
1591
1592 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1593 {
1594         int i;
1595         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1596         int vertstring_length = 0;
1597         int geomstring_length = 0;
1598         int fragstring_length = 0;
1599         char *t;
1600         char *vertexstring, *geometrystring, *fragmentstring;
1601         char *vertstring, *geomstring, *fragstring;
1602         char permutationname[256];
1603         char cachename[256];
1604         int vertstrings_count = 0;
1605         int geomstrings_count = 0;
1606         int fragstrings_count = 0;
1607         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1608         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1609         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1610
1611         if (p->compiled)
1612                 return;
1613         p->compiled = true;
1614         p->vertexshader = NULL;
1615         p->pixelshader = NULL;
1616
1617         permutationname[0] = 0;
1618         cachename[0] = 0;
1619         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1620         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1621         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1622
1623         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1624         strlcat(cachename, "hlsl/", sizeof(cachename));
1625
1626         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1627         vertstrings_count = 0;
1628         geomstrings_count = 0;
1629         fragstrings_count = 0;
1630         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1631         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1632         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1633
1634         // the first pretext is which type of shader to compile as
1635         // (later these will all be bound together as a program object)
1636         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1637         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1638         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1639
1640         // the second pretext is the mode (for example a light source)
1641         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1642         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1643         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1644         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1645         strlcat(cachename, modeinfo->name, sizeof(cachename));
1646
1647         // now add all the permutation pretexts
1648         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1649         {
1650                 if (permutation & (1<<i))
1651                 {
1652                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1653                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1654                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1655                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1656                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1657                 }
1658                 else
1659                 {
1660                         // keep line numbers correct
1661                         vertstrings_list[vertstrings_count++] = "\n";
1662                         geomstrings_list[geomstrings_count++] = "\n";
1663                         fragstrings_list[fragstrings_count++] = "\n";
1664                 }
1665         }
1666
1667         // add static parms
1668         R_CompileShader_AddStaticParms(mode, permutation);
1669         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1670         vertstrings_count += shaderstaticparms_count;
1671         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1672         geomstrings_count += shaderstaticparms_count;
1673         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1674         fragstrings_count += shaderstaticparms_count;
1675
1676         // replace spaces in the cachename with _ characters
1677         for (i = 0;cachename[i];i++)
1678                 if (cachename[i] == ' ')
1679                         cachename[i] = '_';
1680
1681         // now append the shader text itself
1682         vertstrings_list[vertstrings_count++] = vertexstring;
1683         geomstrings_list[geomstrings_count++] = geometrystring;
1684         fragstrings_list[fragstrings_count++] = fragmentstring;
1685
1686         // if any sources were NULL, clear the respective list
1687         if (!vertexstring)
1688                 vertstrings_count = 0;
1689         if (!geometrystring)
1690                 geomstrings_count = 0;
1691         if (!fragmentstring)
1692                 fragstrings_count = 0;
1693
1694         vertstring_length = 0;
1695         for (i = 0;i < vertstrings_count;i++)
1696                 vertstring_length += strlen(vertstrings_list[i]);
1697         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1698         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1699                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1700
1701         geomstring_length = 0;
1702         for (i = 0;i < geomstrings_count;i++)
1703                 geomstring_length += strlen(geomstrings_list[i]);
1704         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1705         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1706                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1707
1708         fragstring_length = 0;
1709         for (i = 0;i < fragstrings_count;i++)
1710                 fragstring_length += strlen(fragstrings_list[i]);
1711         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1712         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1713                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1714
1715         // try to load the cached shader, or generate one
1716         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1717
1718         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1719                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1720         else
1721                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1722
1723         // free the strings
1724         if (vertstring)
1725                 Mem_Free(vertstring);
1726         if (geomstring)
1727                 Mem_Free(geomstring);
1728         if (fragstring)
1729                 Mem_Free(fragstring);
1730         if (vertexstring)
1731                 Mem_Free(vertexstring);
1732         if (geometrystring)
1733                 Mem_Free(geometrystring);
1734         if (fragmentstring)
1735                 Mem_Free(fragmentstring);
1736 }
1737
1738 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 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);}
1741 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);}
1742 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);}
1743 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);}
1744
1745 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1746 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1747 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);}
1748 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);}
1749 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);}
1750 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);}
1751
1752 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1753 {
1754         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1755         if (r_hlsl_permutation != perm)
1756         {
1757                 r_hlsl_permutation = perm;
1758                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1759                 {
1760                         if (!r_hlsl_permutation->compiled)
1761                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1762                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1763                         {
1764                                 // remove features until we find a valid permutation
1765                                 int i;
1766                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1767                                 {
1768                                         // reduce i more quickly whenever it would not remove any bits
1769                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1770                                         if (!(permutation & j))
1771                                                 continue;
1772                                         permutation -= j;
1773                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1774                                         if (!r_hlsl_permutation->compiled)
1775                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1776                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1777                                                 break;
1778                                 }
1779                                 if (i >= SHADERPERMUTATION_COUNT)
1780                                 {
1781                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1782                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1783                                         return; // no bit left to clear, entire mode is broken
1784                                 }
1785                         }
1786                 }
1787                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1788                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1789         }
1790         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1791         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1792         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1793 }
1794 #endif
1795
1796 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1797 {
1798         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1799         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1800         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1801         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1802 }
1803
1804 void R_GLSL_Restart_f(void)
1805 {
1806         unsigned int i, limit;
1807         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1808                 Mem_Free(glslshaderstring);
1809         glslshaderstring = NULL;
1810         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1811                 Mem_Free(hlslshaderstring);
1812         hlslshaderstring = NULL;
1813         switch(vid.renderpath)
1814         {
1815         case RENDERPATH_D3D9:
1816 #ifdef SUPPORTD3D
1817                 {
1818                         r_hlsl_permutation_t *p;
1819                         r_hlsl_permutation = NULL;
1820                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1821                         for (i = 0;i < limit;i++)
1822                         {
1823                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1824                                 {
1825                                         if (p->vertexshader)
1826                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1827                                         if (p->pixelshader)
1828                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1829                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1830                                 }
1831                         }
1832                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1833                 }
1834 #endif
1835                 break;
1836         case RENDERPATH_D3D10:
1837                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1838                 break;
1839         case RENDERPATH_D3D11:
1840                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1841                 break;
1842         case RENDERPATH_GL20:
1843         case RENDERPATH_GLES2:
1844                 {
1845                         r_glsl_permutation_t *p;
1846                         r_glsl_permutation = NULL;
1847                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1848                         for (i = 0;i < limit;i++)
1849                         {
1850                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1851                                 {
1852                                         GL_Backend_FreeProgram(p->program);
1853                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1854                                 }
1855                         }
1856                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1857                 }
1858                 break;
1859         case RENDERPATH_GL11:
1860         case RENDERPATH_GL13:
1861         case RENDERPATH_GLES1:
1862                 break;
1863         case RENDERPATH_SOFT:
1864                 break;
1865         }
1866 }
1867
1868 static void R_GLSL_DumpShader_f(void)
1869 {
1870         int i;
1871         qfile_t *file;
1872
1873         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1874         if (file)
1875         {
1876                 FS_Print(file, "/* The engine may define the following macros:\n");
1877                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1878                 for (i = 0;i < SHADERMODE_COUNT;i++)
1879                         FS_Print(file, glslshadermodeinfo[i].pretext);
1880                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1881                         FS_Print(file, shaderpermutationinfo[i].pretext);
1882                 FS_Print(file, "*/\n");
1883                 FS_Print(file, builtinshaderstring);
1884                 FS_Close(file);
1885                 Con_Printf("glsl/default.glsl written\n");
1886         }
1887         else
1888                 Con_Printf("failed to write to glsl/default.glsl\n");
1889
1890         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1891         if (file)
1892         {
1893                 FS_Print(file, "/* The engine may define the following macros:\n");
1894                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1895                 for (i = 0;i < SHADERMODE_COUNT;i++)
1896                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1897                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1898                         FS_Print(file, shaderpermutationinfo[i].pretext);
1899                 FS_Print(file, "*/\n");
1900                 FS_Print(file, builtinhlslshaderstring);
1901                 FS_Close(file);
1902                 Con_Printf("hlsl/default.hlsl written\n");
1903         }
1904         else
1905                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1906 }
1907
1908 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1909 {
1910         unsigned int permutation = 0;
1911         if (r_trippy.integer && !notrippy)
1912                 permutation |= SHADERPERMUTATION_TRIPPY;
1913         permutation |= SHADERPERMUTATION_VIEWTINT;
1914         if (first)
1915                 permutation |= SHADERPERMUTATION_DIFFUSE;
1916         if (second)
1917                 permutation |= SHADERPERMUTATION_SPECULAR;
1918         if (texturemode == GL_MODULATE)
1919                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1920         else if (texturemode == GL_ADD)
1921                 permutation |= SHADERPERMUTATION_GLOW;
1922         else if (texturemode == GL_DECAL)
1923                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1924         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1925                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1926         if (suppresstexalpha)
1927                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1928         if (!second)
1929                 texturemode = GL_MODULATE;
1930         if (vid.allowalphatocoverage)
1931                 GL_AlphaToCoverage(false);
1932         switch (vid.renderpath)
1933         {
1934         case RENDERPATH_D3D9:
1935 #ifdef SUPPORTD3D
1936                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1937                 R_Mesh_TexBind(GL20TU_FIRST , first );
1938                 R_Mesh_TexBind(GL20TU_SECOND, second);
1939                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1940                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1941 #endif
1942                 break;
1943         case RENDERPATH_D3D10:
1944                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1945                 break;
1946         case RENDERPATH_D3D11:
1947                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1948                 break;
1949         case RENDERPATH_GL20:
1950         case RENDERPATH_GLES2:
1951                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1952                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1953                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1954                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1955                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1956                 break;
1957         case RENDERPATH_GL13:
1958         case RENDERPATH_GLES1:
1959                 R_Mesh_TexBind(0, first );
1960                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1961                 R_Mesh_TexBind(1, second);
1962                 if (second)
1963                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1964                 break;
1965         case RENDERPATH_GL11:
1966                 R_Mesh_TexBind(0, first );
1967                 break;
1968         case RENDERPATH_SOFT:
1969                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1970                 R_Mesh_TexBind(GL20TU_FIRST , first );
1971                 R_Mesh_TexBind(GL20TU_SECOND, second);
1972                 break;
1973         }
1974 }
1975
1976 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1977 {
1978         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1979 }
1980
1981 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1982 {
1983         unsigned int permutation = 0;
1984         if (r_trippy.integer && !notrippy)
1985                 permutation |= SHADERPERMUTATION_TRIPPY;
1986         if (depthrgb)
1987                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1988         if (vid.allowalphatocoverage)
1989                 GL_AlphaToCoverage(false);
1990         switch (vid.renderpath)
1991         {
1992         case RENDERPATH_D3D9:
1993 #ifdef SUPPORTD3D
1994                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1995 #endif
1996                 break;
1997         case RENDERPATH_D3D10:
1998                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1999                 break;
2000         case RENDERPATH_D3D11:
2001                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2002                 break;
2003         case RENDERPATH_GL20:
2004         case RENDERPATH_GLES2:
2005                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2006                 break;
2007         case RENDERPATH_GL13:
2008         case RENDERPATH_GLES1:
2009                 R_Mesh_TexBind(0, 0);
2010                 R_Mesh_TexBind(1, 0);
2011                 break;
2012         case RENDERPATH_GL11:
2013                 R_Mesh_TexBind(0, 0);
2014                 break;
2015         case RENDERPATH_SOFT:
2016                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2017                 break;
2018         }
2019 }
2020
2021 void R_SetupShader_ShowDepth(qboolean notrippy)
2022 {
2023         int permutation = 0;
2024         if (r_trippy.integer && !notrippy)
2025                 permutation |= SHADERPERMUTATION_TRIPPY;
2026         if (vid.allowalphatocoverage)
2027                 GL_AlphaToCoverage(false);
2028         switch (vid.renderpath)
2029         {
2030         case RENDERPATH_D3D9:
2031 #ifdef SUPPORTHLSL
2032                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2033 #endif
2034                 break;
2035         case RENDERPATH_D3D10:
2036                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2037                 break;
2038         case RENDERPATH_D3D11:
2039                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2040                 break;
2041         case RENDERPATH_GL20:
2042         case RENDERPATH_GLES2:
2043                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2044                 break;
2045         case RENDERPATH_GL13:
2046         case RENDERPATH_GLES1:
2047                 break;
2048         case RENDERPATH_GL11:
2049                 break;
2050         case RENDERPATH_SOFT:
2051                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2052                 break;
2053         }
2054 }
2055
2056 extern qboolean r_shadow_usingdeferredprepass;
2057 extern rtexture_t *r_shadow_attenuationgradienttexture;
2058 extern rtexture_t *r_shadow_attenuation2dtexture;
2059 extern rtexture_t *r_shadow_attenuation3dtexture;
2060 extern qboolean r_shadow_usingshadowmap2d;
2061 extern qboolean r_shadow_usingshadowmaportho;
2062 extern float r_shadow_shadowmap_texturescale[2];
2063 extern float r_shadow_shadowmap_parameters[4];
2064 extern qboolean r_shadow_shadowmapvsdct;
2065 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2066 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2067 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2068 extern matrix4x4_t r_shadow_shadowmapmatrix;
2069 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2070 extern int r_shadow_prepass_width;
2071 extern int r_shadow_prepass_height;
2072 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2073 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2074 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2075 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2076
2077 #define BLENDFUNC_ALLOWS_COLORMOD      1
2078 #define BLENDFUNC_ALLOWS_FOG           2
2079 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2080 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2081 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2082 static int R_BlendFuncFlags(int src, int dst)
2083 {
2084         int r = 0;
2085
2086         // a blendfunc allows colormod if:
2087         // a) it can never keep the destination pixel invariant, or
2088         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2089         // this is to prevent unintended side effects from colormod
2090
2091         // a blendfunc allows fog if:
2092         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2093         // this is to prevent unintended side effects from fog
2094
2095         // these checks are the output of fogeval.pl
2096
2097         r |= BLENDFUNC_ALLOWS_COLORMOD;
2098         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2099         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2100         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2101         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2102         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2103         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2104         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2105         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2106         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2107         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2108         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2109         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2110         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2111         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2112         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2113         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2114         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2115         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2116         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2117         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2118         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2119
2120         return r;
2121 }
2122
2123 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)
2124 {
2125         // select a permutation of the lighting shader appropriate to this
2126         // combination of texture, entity, light source, and fogging, only use the
2127         // minimum features necessary to avoid wasting rendering time in the
2128         // fragment shader on features that are not being used
2129         unsigned int permutation = 0;
2130         unsigned int mode = 0;
2131         int blendfuncflags;
2132         static float dummy_colormod[3] = {1, 1, 1};
2133         float *colormod = rsurface.colormod;
2134         float m16f[16];
2135         matrix4x4_t tempmatrix;
2136         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2137         if (r_trippy.integer && !notrippy)
2138                 permutation |= SHADERPERMUTATION_TRIPPY;
2139         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2140                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2141         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2142                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2143         if (rsurfacepass == RSURFPASS_BACKGROUND)
2144         {
2145                 // distorted background
2146                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2147                 {
2148                         mode = SHADERMODE_WATER;
2149                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2150                         {
2151                                 // this is the right thing to do for wateralpha
2152                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2153                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2154                         }
2155                         else
2156                         {
2157                                 // this is the right thing to do for entity alpha
2158                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2159                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2160                         }
2161                 }
2162                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2163                 {
2164                         mode = SHADERMODE_REFRACTION;
2165                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2166                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2167                 }
2168                 else
2169                 {
2170                         mode = SHADERMODE_GENERIC;
2171                         permutation |= SHADERPERMUTATION_DIFFUSE;
2172                         GL_BlendFunc(GL_ONE, GL_ZERO);
2173                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2174                 }
2175                 if (vid.allowalphatocoverage)
2176                         GL_AlphaToCoverage(false);
2177         }
2178         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2179         {
2180                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2181                 {
2182                         switch(rsurface.texture->offsetmapping)
2183                         {
2184                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2185                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2186                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2187                         case OFFSETMAPPING_OFF: break;
2188                         }
2189                 }
2190                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2191                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2192                 // normalmap (deferred prepass), may use alpha test on diffuse
2193                 mode = SHADERMODE_DEFERREDGEOMETRY;
2194                 GL_BlendFunc(GL_ONE, GL_ZERO);
2195                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2196                 if (vid.allowalphatocoverage)
2197                         GL_AlphaToCoverage(false);
2198         }
2199         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2200         {
2201                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2202                 {
2203                         switch(rsurface.texture->offsetmapping)
2204                         {
2205                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2206                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2207                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2208                         case OFFSETMAPPING_OFF: break;
2209                         }
2210                 }
2211                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2212                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2213                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2214                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2215                 // light source
2216                 mode = SHADERMODE_LIGHTSOURCE;
2217                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2218                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2219                 if (diffusescale > 0)
2220                         permutation |= SHADERPERMUTATION_DIFFUSE;
2221                 if (specularscale > 0)
2222                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2223                 if (r_refdef.fogenabled)
2224                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2225                 if (rsurface.texture->colormapping)
2226                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2227                 if (r_shadow_usingshadowmap2d)
2228                 {
2229                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2230                         if(r_shadow_shadowmapvsdct)
2231                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2232
2233                         if (r_shadow_shadowmap2ddepthbuffer)
2234                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2235                 }
2236                 if (rsurface.texture->reflectmasktexture)
2237                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2238                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2239                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2240                 if (vid.allowalphatocoverage)
2241                         GL_AlphaToCoverage(false);
2242         }
2243         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2244         {
2245                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2246                 {
2247                         switch(rsurface.texture->offsetmapping)
2248                         {
2249                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2250                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2251                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2252                         case OFFSETMAPPING_OFF: break;
2253                         }
2254                 }
2255                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2256                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2257                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2258                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2259                 // unshaded geometry (fullbright or ambient model lighting)
2260                 mode = SHADERMODE_FLATCOLOR;
2261                 ambientscale = diffusescale = specularscale = 0;
2262                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2263                         permutation |= SHADERPERMUTATION_GLOW;
2264                 if (r_refdef.fogenabled)
2265                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2266                 if (rsurface.texture->colormapping)
2267                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2268                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2269                 {
2270                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2271                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2272
2273                         if (r_shadow_shadowmap2ddepthbuffer)
2274                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2275                 }
2276                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2277                         permutation |= SHADERPERMUTATION_REFLECTION;
2278                 if (rsurface.texture->reflectmasktexture)
2279                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2280                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2281                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2282                 // when using alphatocoverage, we don't need alphakill
2283                 if (vid.allowalphatocoverage)
2284                 {
2285                         if (r_transparent_alphatocoverage.integer)
2286                         {
2287                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2288                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2289                         }
2290                         else
2291                                 GL_AlphaToCoverage(false);
2292                 }
2293         }
2294         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2295         {
2296                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2297                 {
2298                         switch(rsurface.texture->offsetmapping)
2299                         {
2300                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2301                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2302                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2303                         case OFFSETMAPPING_OFF: break;
2304                         }
2305                 }
2306                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2307                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2308                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2309                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2310                 // directional model lighting
2311                 mode = SHADERMODE_LIGHTDIRECTION;
2312                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2313                         permutation |= SHADERPERMUTATION_GLOW;
2314                 permutation |= SHADERPERMUTATION_DIFFUSE;
2315                 if (specularscale > 0)
2316                         permutation |= SHADERPERMUTATION_SPECULAR;
2317                 if (r_refdef.fogenabled)
2318                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2319                 if (rsurface.texture->colormapping)
2320                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2321                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2322                 {
2323                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2324                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2325
2326                         if (r_shadow_shadowmap2ddepthbuffer)
2327                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2328                 }
2329                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2330                         permutation |= SHADERPERMUTATION_REFLECTION;
2331                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2332                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2333                 if (rsurface.texture->reflectmasktexture)
2334                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2335                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2336                 {
2337                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2338                         if (r_shadow_bouncegriddirectional)
2339                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2340                 }
2341                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2342                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2343                 // when using alphatocoverage, we don't need alphakill
2344                 if (vid.allowalphatocoverage)
2345                 {
2346                         if (r_transparent_alphatocoverage.integer)
2347                         {
2348                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2349                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2350                         }
2351                         else
2352                                 GL_AlphaToCoverage(false);
2353                 }
2354         }
2355         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2356         {
2357                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2358                 {
2359                         switch(rsurface.texture->offsetmapping)
2360                         {
2361                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2362                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2363                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2364                         case OFFSETMAPPING_OFF: break;
2365                         }
2366                 }
2367                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2368                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2369                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2370                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2371                 // ambient model lighting
2372                 mode = SHADERMODE_LIGHTDIRECTION;
2373                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2374                         permutation |= SHADERPERMUTATION_GLOW;
2375                 if (r_refdef.fogenabled)
2376                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2377                 if (rsurface.texture->colormapping)
2378                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2379                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2380                 {
2381                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2382                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2383
2384                         if (r_shadow_shadowmap2ddepthbuffer)
2385                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2386                 }
2387                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2388                         permutation |= SHADERPERMUTATION_REFLECTION;
2389                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2390                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2391                 if (rsurface.texture->reflectmasktexture)
2392                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2393                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2394                 {
2395                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2396                         if (r_shadow_bouncegriddirectional)
2397                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2398                 }
2399                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2400                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2401                 // when using alphatocoverage, we don't need alphakill
2402                 if (vid.allowalphatocoverage)
2403                 {
2404                         if (r_transparent_alphatocoverage.integer)
2405                         {
2406                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2407                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2408                         }
2409                         else
2410                                 GL_AlphaToCoverage(false);
2411                 }
2412         }
2413         else
2414         {
2415                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2416                 {
2417                         switch(rsurface.texture->offsetmapping)
2418                         {
2419                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2420                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2421                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2422                         case OFFSETMAPPING_OFF: break;
2423                         }
2424                 }
2425                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2426                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2427                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2428                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2429                 // lightmapped wall
2430                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2431                         permutation |= SHADERPERMUTATION_GLOW;
2432                 if (r_refdef.fogenabled)
2433                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2434                 if (rsurface.texture->colormapping)
2435                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2436                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2437                 {
2438                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2439                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2440
2441                         if (r_shadow_shadowmap2ddepthbuffer)
2442                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2443                 }
2444                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2445                         permutation |= SHADERPERMUTATION_REFLECTION;
2446                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2447                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2448                 if (rsurface.texture->reflectmasktexture)
2449                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2450                 if (FAKELIGHT_ENABLED)
2451                 {
2452                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2453                         mode = SHADERMODE_FAKELIGHT;
2454                         permutation |= SHADERPERMUTATION_DIFFUSE;
2455                         if (specularscale > 0)
2456                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2457                 }
2458                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2459                 {
2460                         // deluxemapping (light direction texture)
2461                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2462                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2463                         else
2464                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2465                         permutation |= SHADERPERMUTATION_DIFFUSE;
2466                         if (specularscale > 0)
2467                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2468                 }
2469                 else if (r_glsl_deluxemapping.integer >= 2)
2470                 {
2471                         // fake deluxemapping (uniform light direction in tangentspace)
2472                         if (rsurface.uselightmaptexture)
2473                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2474                         else
2475                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2476                         permutation |= SHADERPERMUTATION_DIFFUSE;
2477                         if (specularscale > 0)
2478                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2479                 }
2480                 else if (rsurface.uselightmaptexture)
2481                 {
2482                         // ordinary lightmapping (q1bsp, q3bsp)
2483                         mode = SHADERMODE_LIGHTMAP;
2484                 }
2485                 else
2486                 {
2487                         // ordinary vertex coloring (q3bsp)
2488                         mode = SHADERMODE_VERTEXCOLOR;
2489                 }
2490                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2491                 {
2492                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2493                         if (r_shadow_bouncegriddirectional)
2494                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2495                 }
2496                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2497                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2498                 // when using alphatocoverage, we don't need alphakill
2499                 if (vid.allowalphatocoverage)
2500                 {
2501                         if (r_transparent_alphatocoverage.integer)
2502                         {
2503                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2504                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2505                         }
2506                         else
2507                                 GL_AlphaToCoverage(false);
2508                 }
2509         }
2510         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2511                 colormod = dummy_colormod;
2512         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2513                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2514         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2515                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2516         switch(vid.renderpath)
2517         {
2518         case RENDERPATH_D3D9:
2519 #ifdef SUPPORTD3D
2520                 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);
2521                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2522                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2523                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2524                 if (mode == SHADERMODE_LIGHTSOURCE)
2525                 {
2526                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2527                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2528                 }
2529                 else
2530                 {
2531                         if (mode == SHADERMODE_LIGHTDIRECTION)
2532                         {
2533                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2534                         }
2535                 }
2536                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2537                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2538                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2539                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2540                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2541
2542                 if (mode == SHADERMODE_LIGHTSOURCE)
2543                 {
2544                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2545                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2546                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2547                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2548                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2549
2550                         // additive passes are only darkened by fog, not tinted
2551                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2552                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2553                 }
2554                 else
2555                 {
2556                         if (mode == SHADERMODE_FLATCOLOR)
2557                         {
2558                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2559                         }
2560                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2561                         {
2562                                 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]);
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2564                                 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);
2565                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2566                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2567                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2569                         }
2570                         else
2571                         {
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2573                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2574                                 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);
2575                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2576                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2577                         }
2578                         // additive passes are only darkened by fog, not tinted
2579                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2581                         else
2582                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2583                         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);
2584                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2585                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2586                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2587                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2588                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2589                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2590                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2591                         if (mode == SHADERMODE_WATER)
2592                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2593                 }
2594                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2595                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2596                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2597                 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));
2598                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2599                 if (rsurface.texture->pantstexture)
2600                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2601                 else
2602                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2603                 if (rsurface.texture->shirttexture)
2604                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2605                 else
2606                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2607                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2608                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2609                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2610                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2611                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2612                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2613                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2614                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2615                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2616                         );
2617                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2618                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2619                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2620                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2621
2622                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2623                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2624                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2625                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2626                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2627                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2628                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2629                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2630                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2631                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2632                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2633                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2634                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2635                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2636                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2637                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2638                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2639                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2640                 {
2641                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2642                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2643                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2644                 }
2645                 else
2646                 {
2647                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2648                 }
2649 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2650                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2651                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2652                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2653                 {
2654                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2655                         if (rsurface.rtlight)
2656                         {
2657                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2658                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2659                         }
2660                 }
2661 #endif
2662                 break;
2663         case RENDERPATH_D3D10:
2664                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2665                 break;
2666         case RENDERPATH_D3D11:
2667                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2668                 break;
2669         case RENDERPATH_GL20:
2670         case RENDERPATH_GLES2:
2671                 if (!vid.useinterleavedarrays)
2672                 {
2673                         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);
2674                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2675                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2676                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2677                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2678                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2679                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2680                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2681                 }
2682                 else
2683                 {
2684                         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);
2685                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2686                 }
2687                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2688                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2689                 if (mode == SHADERMODE_LIGHTSOURCE)
2690                 {
2691                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2692                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2693                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2694                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2695                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2696                         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);
2697         
2698                         // additive passes are only darkened by fog, not tinted
2699                         if (r_glsl_permutation->loc_FogColor >= 0)
2700                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2701                         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);
2702                 }
2703                 else
2704                 {
2705                         if (mode == SHADERMODE_FLATCOLOR)
2706                         {
2707                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2708                         }
2709                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2710                         {
2711                                 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]);
2712                                 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]);
2713                                 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);
2714                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2715                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2716                                 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]);
2717                                 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]);
2718                         }
2719                         else
2720                         {
2721                                 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]);
2722                                 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]);
2723                                 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);
2724                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2725                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2726                         }
2727                         // additive passes are only darkened by fog, not tinted
2728                         if (r_glsl_permutation->loc_FogColor >= 0)
2729                         {
2730                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2731                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2732                                 else
2733                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2734                         }
2735                         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);
2736                         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]);
2737                         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]);
2738                         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]);
2739                         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]);
2740                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2741                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2742                         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);
2743                         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]);
2744                 }
2745                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2746                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2747                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2748                 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]);
2749                 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]);
2750
2751                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2752                 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));
2753                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2754                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2755                 {
2756                         if (rsurface.texture->pantstexture)
2757                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2758                         else
2759                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2760                 }
2761                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2762                 {
2763                         if (rsurface.texture->shirttexture)
2764                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2765                         else
2766                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2767                 }
2768                 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]);
2769                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2770                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2771                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2772                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2773                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2774                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2775                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2776                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2777                         );
2778                 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);
2779                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2780                 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]);
2781                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2782                 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);}
2783                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2784
2785                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2786                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2787                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2788                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2789                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2790                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2791                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2792                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2793                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2794                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2795                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2796                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2797                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2798                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2799                 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);
2800                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2801                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2802                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2803                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2804                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2805                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2806                 {
2807                         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);
2808                         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);
2809                         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);
2810                 }
2811                 else
2812                 {
2813                         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);
2814                 }
2815                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2816                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2817                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2818                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2819                 {
2820                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2821                         if (rsurface.rtlight)
2822                         {
2823                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2824                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2825                         }
2826                 }
2827                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2828                 CHECKGLERROR
2829                 break;
2830         case RENDERPATH_GL11:
2831         case RENDERPATH_GL13:
2832         case RENDERPATH_GLES1:
2833                 break;
2834         case RENDERPATH_SOFT:
2835                 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);
2836                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2837                 R_SetupShader_SetPermutationSoft(mode, permutation);
2838                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2839                 if (mode == SHADERMODE_LIGHTSOURCE)
2840                 {
2841                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2842                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2843                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2844                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2845                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2846                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2847         
2848                         // additive passes are only darkened by fog, not tinted
2849                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2850                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2851                 }
2852                 else
2853                 {
2854                         if (mode == SHADERMODE_FLATCOLOR)
2855                         {
2856                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2857                         }
2858                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2859                         {
2860                                 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]);
2861                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2862                                 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);
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2865                                 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]);
2866                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2867                         }
2868                         else
2869                         {
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2872                                 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);
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2875                         }
2876                         // additive passes are only darkened by fog, not tinted
2877                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2879                         else
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2881                         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);
2882                         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]);
2883                         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]);
2884                         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]);
2885                         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]);
2886                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2887                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2888                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2889                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2890                 }
2891                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2892                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2893                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2894                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2895                 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]);
2896
2897                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2898                 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));
2899                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2900                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2901                 {
2902                         if (rsurface.texture->pantstexture)
2903                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2904                         else
2905                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2906                 }
2907                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2908                 {
2909                         if (rsurface.texture->shirttexture)
2910                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2911                         else
2912                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2913                 }
2914                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2915                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2916                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2917                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2918                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2919                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2920                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2921                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2922                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2923                         );
2924                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2925                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2926                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2927                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2928
2929                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2930                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2931                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2932                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2933                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2934                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2935                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2936                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2937                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2938                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2939                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2940                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2941                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2942                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2943                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2944                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2945                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2946                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2947                 {
2948                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2949                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2950                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2951                 }
2952                 else
2953                 {
2954                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2955                 }
2956 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2957                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2958                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2959                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2960                 {
2961                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2962                         if (rsurface.rtlight)
2963                         {
2964                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2965                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2966                         }
2967                 }
2968                 break;
2969         }
2970 }
2971
2972 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2973 {
2974         // select a permutation of the lighting shader appropriate to this
2975         // combination of texture, entity, light source, and fogging, only use the
2976         // minimum features necessary to avoid wasting rendering time in the
2977         // fragment shader on features that are not being used
2978         unsigned int permutation = 0;
2979         unsigned int mode = 0;
2980         const float *lightcolorbase = rtlight->currentcolor;
2981         float ambientscale = rtlight->ambientscale;
2982         float diffusescale = rtlight->diffusescale;
2983         float specularscale = rtlight->specularscale;
2984         // this is the location of the light in view space
2985         vec3_t viewlightorigin;
2986         // this transforms from view space (camera) to light space (cubemap)
2987         matrix4x4_t viewtolight;
2988         matrix4x4_t lighttoview;
2989         float viewtolight16f[16];
2990         // light source
2991         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2992         if (rtlight->currentcubemap != r_texture_whitecube)
2993                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2994         if (diffusescale > 0)
2995                 permutation |= SHADERPERMUTATION_DIFFUSE;
2996         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2997                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2998         if (r_shadow_usingshadowmap2d)
2999         {
3000                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3001                 if (r_shadow_shadowmapvsdct)
3002                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3003
3004                 if (r_shadow_shadowmap2ddepthbuffer)
3005                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3006         }
3007         if (vid.allowalphatocoverage)
3008                 GL_AlphaToCoverage(false);
3009         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3010         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3011         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3012         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3013         switch(vid.renderpath)
3014         {
3015         case RENDERPATH_D3D9:
3016 #ifdef SUPPORTD3D
3017                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3018                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3019                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3020                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3021                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3022                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3023                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3024                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3025                 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);
3026                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3027                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3028
3029                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3030                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3031                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3032                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3033                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3034 #endif
3035                 break;
3036         case RENDERPATH_D3D10:
3037                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3038                 break;
3039         case RENDERPATH_D3D11:
3040                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3041                 break;
3042         case RENDERPATH_GL20:
3043         case RENDERPATH_GLES2:
3044                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3045                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3046                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3047                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3048                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3049                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3050                 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]);
3051                 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]);
3052                 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);
3053                 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]);
3054                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3055
3056                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3057                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3058                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3059                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3060                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3061                 break;
3062         case RENDERPATH_GL11:
3063         case RENDERPATH_GL13:
3064         case RENDERPATH_GLES1:
3065                 break;
3066         case RENDERPATH_SOFT:
3067                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3068                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3069                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3070                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3071                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3072                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3073                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3074                 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]);
3075                 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);
3076                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3077                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3078
3079                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3080                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3081                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3082                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3083                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3084                 break;
3085         }
3086 }
3087
3088 #define SKINFRAME_HASH 1024
3089
3090 typedef struct
3091 {
3092         int loadsequence; // incremented each level change
3093         memexpandablearray_t array;
3094         skinframe_t *hash[SKINFRAME_HASH];
3095 }
3096 r_skinframe_t;
3097 r_skinframe_t r_skinframe;
3098
3099 void R_SkinFrame_PrepareForPurge(void)
3100 {
3101         r_skinframe.loadsequence++;
3102         // wrap it without hitting zero
3103         if (r_skinframe.loadsequence >= 200)
3104                 r_skinframe.loadsequence = 1;
3105 }
3106
3107 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3108 {
3109         if (!skinframe)
3110                 return;
3111         // mark the skinframe as used for the purging code
3112         skinframe->loadsequence = r_skinframe.loadsequence;
3113 }
3114
3115 void R_SkinFrame_Purge(void)
3116 {
3117         int i;
3118         skinframe_t *s;
3119         for (i = 0;i < SKINFRAME_HASH;i++)
3120         {
3121                 for (s = r_skinframe.hash[i];s;s = s->next)
3122                 {
3123                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3124                         {
3125                                 if (s->merged == s->base)
3126                                         s->merged = NULL;
3127                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3128                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3129                                 R_PurgeTexture(s->merged);s->merged = NULL;
3130                                 R_PurgeTexture(s->base  );s->base   = NULL;
3131                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3132                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3133                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3134                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3135                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3136                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3137                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3138                                 s->loadsequence = 0;
3139                         }
3140                 }
3141         }
3142 }
3143
3144 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3145         skinframe_t *item;
3146         char basename[MAX_QPATH];
3147
3148         Image_StripImageExtension(name, basename, sizeof(basename));
3149
3150         if( last == NULL ) {
3151                 int hashindex;
3152                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3153                 item = r_skinframe.hash[hashindex];
3154         } else {
3155                 item = last->next;
3156         }
3157
3158         // linearly search through the hash bucket
3159         for( ; item ; item = item->next ) {
3160                 if( !strcmp( item->basename, basename ) ) {
3161                         return item;
3162                 }
3163         }
3164         return NULL;
3165 }
3166
3167 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3168 {
3169         skinframe_t *item;
3170         int hashindex;
3171         char basename[MAX_QPATH];
3172
3173         Image_StripImageExtension(name, basename, sizeof(basename));
3174
3175         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3176         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3177                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3178                         break;
3179
3180         if (!item) {
3181                 rtexture_t *dyntexture;
3182                 // check whether its a dynamic texture
3183                 dyntexture = CL_GetDynTexture( basename );
3184                 if (!add && !dyntexture)
3185                         return NULL;
3186                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3187                 memset(item, 0, sizeof(*item));
3188                 strlcpy(item->basename, basename, sizeof(item->basename));
3189                 item->base = dyntexture; // either NULL or dyntexture handle
3190                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3191                 item->comparewidth = comparewidth;
3192                 item->compareheight = compareheight;
3193                 item->comparecrc = comparecrc;
3194                 item->next = r_skinframe.hash[hashindex];
3195                 r_skinframe.hash[hashindex] = item;
3196         }
3197         else if (textureflags & TEXF_FORCE_RELOAD)
3198         {
3199                 rtexture_t *dyntexture;
3200                 // check whether its a dynamic texture
3201                 dyntexture = CL_GetDynTexture( basename );
3202                 if (!add && !dyntexture)
3203                         return NULL;
3204                 if (item->merged == item->base)
3205                         item->merged = NULL;
3206                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3207                 R_PurgeTexture(item->stain );item->stain  = NULL;
3208                 R_PurgeTexture(item->merged);item->merged = NULL;
3209                 R_PurgeTexture(item->base  );item->base   = NULL;
3210                 R_PurgeTexture(item->pants );item->pants  = NULL;
3211                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3212                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3213                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3214                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3215                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3216         R_PurgeTexture(item->reflect);item->reflect = NULL;
3217                 item->loadsequence = 0;
3218         }
3219         else if( item->base == NULL )
3220         {
3221                 rtexture_t *dyntexture;
3222                 // check whether its a dynamic texture
3223                 // 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]
3224                 dyntexture = CL_GetDynTexture( basename );
3225                 item->base = dyntexture; // either NULL or dyntexture handle
3226         }
3227
3228         R_SkinFrame_MarkUsed(item);
3229         return item;
3230 }
3231
3232 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3233         { \
3234                 unsigned long long avgcolor[5], wsum; \
3235                 int pix, comp, w; \
3236                 avgcolor[0] = 0; \
3237                 avgcolor[1] = 0; \
3238                 avgcolor[2] = 0; \
3239                 avgcolor[3] = 0; \
3240                 avgcolor[4] = 0; \
3241                 wsum = 0; \
3242                 for(pix = 0; pix < cnt; ++pix) \
3243                 { \
3244                         w = 0; \
3245                         for(comp = 0; comp < 3; ++comp) \
3246                                 w += getpixel; \
3247                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3248                         { \
3249                                 ++wsum; \
3250                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3251                                 w = getpixel; \
3252                                 for(comp = 0; comp < 3; ++comp) \
3253                                         avgcolor[comp] += getpixel * w; \
3254                                 avgcolor[3] += w; \
3255                         } \
3256                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3257                         avgcolor[4] += getpixel; \
3258                 } \
3259                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3260                         avgcolor[3] = 1; \
3261                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3262                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3263                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3264                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3265         }
3266
3267 extern cvar_t gl_picmip;
3268 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3269 {
3270         int j;
3271         unsigned char *pixels;
3272         unsigned char *bumppixels;
3273         unsigned char *basepixels = NULL;
3274         int basepixels_width = 0;
3275         int basepixels_height = 0;
3276         skinframe_t *skinframe;
3277         rtexture_t *ddsbase = NULL;
3278         qboolean ddshasalpha = false;
3279         float ddsavgcolor[4];
3280         char basename[MAX_QPATH];
3281         int miplevel = R_PicmipForFlags(textureflags);
3282         int savemiplevel = miplevel;
3283         int mymiplevel;
3284         char vabuf[1024];
3285
3286         if (cls.state == ca_dedicated)
3287                 return NULL;
3288
3289         // return an existing skinframe if already loaded
3290         // if loading of the first image fails, don't make a new skinframe as it
3291         // would cause all future lookups of this to be missing
3292         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3293         if (skinframe && skinframe->base)
3294                 return skinframe;
3295
3296         Image_StripImageExtension(name, basename, sizeof(basename));
3297
3298         // check for DDS texture file first
3299         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3300         {
3301                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3302                 if (basepixels == NULL)
3303                         return NULL;
3304         }
3305
3306         // FIXME handle miplevel
3307
3308         if (developer_loading.integer)
3309                 Con_Printf("loading skin \"%s\"\n", name);
3310
3311         // we've got some pixels to store, so really allocate this new texture now
3312         if (!skinframe)
3313                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3314         textureflags &= ~TEXF_FORCE_RELOAD;
3315         skinframe->stain = NULL;
3316         skinframe->merged = NULL;
3317         skinframe->base = NULL;
3318         skinframe->pants = NULL;
3319         skinframe->shirt = NULL;
3320         skinframe->nmap = NULL;
3321         skinframe->gloss = NULL;
3322         skinframe->glow = NULL;
3323         skinframe->fog = NULL;
3324         skinframe->reflect = NULL;
3325         skinframe->hasalpha = false;
3326
3327         if (ddsbase)
3328         {
3329                 skinframe->base = ddsbase;
3330                 skinframe->hasalpha = ddshasalpha;
3331                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3332                 if (r_loadfog && skinframe->hasalpha)
3333                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3334                 //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]);
3335         }
3336         else
3337         {
3338                 basepixels_width = image_width;
3339                 basepixels_height = image_height;
3340                 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);
3341                 if (textureflags & TEXF_ALPHA)
3342                 {
3343                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3344                         {
3345                                 if (basepixels[j] < 255)
3346                                 {
3347                                         skinframe->hasalpha = true;
3348                                         break;
3349                                 }
3350                         }
3351                         if (r_loadfog && skinframe->hasalpha)
3352                         {
3353                                 // has transparent pixels
3354                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3355                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3356                                 {
3357                                         pixels[j+0] = 255;
3358                                         pixels[j+1] = 255;
3359                                         pixels[j+2] = 255;
3360                                         pixels[j+3] = basepixels[j+3];
3361                                 }
3362                                 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);
3363                                 Mem_Free(pixels);
3364                         }
3365                 }
3366                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3367 #ifndef USE_GLES2
3368                 //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]);
3369                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3370                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3371                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3372                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3373 #endif
3374         }
3375
3376         if (r_loaddds)
3377         {
3378                 mymiplevel = savemiplevel;
3379                 if (r_loadnormalmap)
3380                         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);
3381                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3382                 if (r_loadgloss)
3383                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3384                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3385                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3386                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3387         }
3388
3389         // _norm is the name used by tenebrae and has been adopted as standard
3390         if (r_loadnormalmap && skinframe->nmap == NULL)
3391         {
3392                 mymiplevel = savemiplevel;
3393                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3394                 {
3395                         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);
3396                         Mem_Free(pixels);
3397                         pixels = NULL;
3398                 }
3399                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3400                 {
3401                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3402                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3403                         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);
3404                         Mem_Free(pixels);
3405                         Mem_Free(bumppixels);
3406                 }
3407                 else if (r_shadow_bumpscale_basetexture.value > 0)
3408                 {
3409                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3410                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3411                         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);
3412                         Mem_Free(pixels);
3413                 }
3414 #ifndef USE_GLES2
3415                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3416                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3417 #endif
3418         }
3419
3420         // _luma is supported only for tenebrae compatibility
3421         // _glow is the preferred name
3422         mymiplevel = savemiplevel;
3423         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))))
3424         {
3425                 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);
3426 #ifndef USE_GLES2
3427                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3428                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3429 #endif
3430                 Mem_Free(pixels);pixels = NULL;
3431         }
3432
3433         mymiplevel = savemiplevel;
3434         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3435         {
3436                 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);
3437 #ifndef USE_GLES2
3438                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3439                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3440 #endif
3441                 Mem_Free(pixels);
3442                 pixels = NULL;
3443         }
3444
3445         mymiplevel = savemiplevel;
3446         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3447         {
3448                 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);
3449 #ifndef USE_GLES2
3450                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3451                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3452 #endif
3453                 Mem_Free(pixels);
3454                 pixels = NULL;
3455         }
3456
3457         mymiplevel = savemiplevel;
3458         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3459         {
3460                 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);
3461 #ifndef USE_GLES2
3462                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3463                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3464 #endif
3465                 Mem_Free(pixels);
3466                 pixels = NULL;
3467         }
3468
3469         mymiplevel = savemiplevel;
3470         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3471         {
3472                 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);
3473 #ifndef USE_GLES2
3474                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3475                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3476 #endif
3477                 Mem_Free(pixels);
3478                 pixels = NULL;
3479         }
3480
3481         if (basepixels)
3482                 Mem_Free(basepixels);
3483
3484         return skinframe;
3485 }
3486
3487 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3488 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3489 {
3490         int i;
3491         unsigned char *temp1, *temp2;
3492         skinframe_t *skinframe;
3493         char vabuf[1024];
3494
3495         if (cls.state == ca_dedicated)
3496                 return NULL;
3497
3498         // if already loaded just return it, otherwise make a new skinframe
3499         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3500         if (skinframe && skinframe->base)
3501                 return skinframe;
3502         textureflags &= ~TEXF_FORCE_RELOAD;
3503
3504         skinframe->stain = NULL;
3505         skinframe->merged = NULL;
3506         skinframe->base = NULL;
3507         skinframe->pants = NULL;
3508         skinframe->shirt = NULL;
3509         skinframe->nmap = NULL;
3510         skinframe->gloss = NULL;
3511         skinframe->glow = NULL;
3512         skinframe->fog = NULL;
3513         skinframe->reflect = NULL;
3514         skinframe->hasalpha = false;
3515
3516         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3517         if (!skindata)
3518                 return NULL;
3519
3520         if (developer_loading.integer)
3521                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3522
3523         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3524         {
3525                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3526                 temp2 = temp1 + width * height * 4;
3527                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3528                 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);
3529                 Mem_Free(temp1);
3530         }
3531         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3532         if (textureflags & TEXF_ALPHA)
3533         {
3534                 for (i = 3;i < width * height * 4;i += 4)
3535                 {
3536                         if (skindata[i] < 255)
3537                         {
3538                                 skinframe->hasalpha = true;
3539                                 break;
3540                         }
3541                 }
3542                 if (r_loadfog && skinframe->hasalpha)
3543                 {
3544                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3545                         memcpy(fogpixels, skindata, width * height * 4);
3546                         for (i = 0;i < width * height * 4;i += 4)
3547                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3548                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3549                         Mem_Free(fogpixels);
3550                 }
3551         }
3552
3553         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3554         //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]);
3555
3556         return skinframe;
3557 }
3558
3559 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3560 {
3561         int i;
3562         int featuresmask;
3563         skinframe_t *skinframe;
3564
3565         if (cls.state == ca_dedicated)
3566                 return NULL;
3567
3568         // if already loaded just return it, otherwise make a new skinframe
3569         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3570         if (skinframe && skinframe->base)
3571                 return skinframe;
3572         textureflags &= ~TEXF_FORCE_RELOAD;
3573
3574         skinframe->stain = NULL;
3575         skinframe->merged = NULL;
3576         skinframe->base = NULL;
3577         skinframe->pants = NULL;
3578         skinframe->shirt = NULL;
3579         skinframe->nmap = NULL;
3580         skinframe->gloss = NULL;
3581         skinframe->glow = NULL;
3582         skinframe->fog = NULL;
3583         skinframe->reflect = NULL;
3584         skinframe->hasalpha = false;
3585
3586         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3587         if (!skindata)
3588                 return NULL;
3589
3590         if (developer_loading.integer)
3591                 Con_Printf("loading quake skin \"%s\"\n", name);
3592
3593         // 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)
3594         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3595         memcpy(skinframe->qpixels, skindata, width*height);
3596         skinframe->qwidth = width;
3597         skinframe->qheight = height;
3598
3599         featuresmask = 0;
3600         for (i = 0;i < width * height;i++)
3601                 featuresmask |= palette_featureflags[skindata[i]];
3602
3603         skinframe->hasalpha = false;
3604         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3605         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3606         skinframe->qgeneratemerged = true;
3607         skinframe->qgeneratebase = skinframe->qhascolormapping;
3608         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3609
3610         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3611         //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]);
3612
3613         return skinframe;
3614 }
3615
3616 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3617 {
3618         int width;
3619         int height;
3620         unsigned char *skindata;
3621         char vabuf[1024];
3622
3623         if (!skinframe->qpixels)
3624                 return;
3625
3626         if (!skinframe->qhascolormapping)
3627                 colormapped = false;
3628
3629         if (colormapped)
3630         {
3631                 if (!skinframe->qgeneratebase)
3632                         return;
3633         }
3634         else
3635         {
3636                 if (!skinframe->qgeneratemerged)
3637                         return;
3638         }
3639
3640         width = skinframe->qwidth;
3641         height = skinframe->qheight;
3642         skindata = skinframe->qpixels;
3643
3644         if (skinframe->qgeneratenmap)
3645         {
3646                 unsigned char *temp1, *temp2;
3647                 skinframe->qgeneratenmap = false;
3648                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3649                 temp2 = temp1 + width * height * 4;
3650                 // use either a custom palette or the quake palette
3651                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3652                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3653                 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);
3654                 Mem_Free(temp1);
3655         }
3656
3657         if (skinframe->qgenerateglow)
3658         {
3659                 skinframe->qgenerateglow = false;
3660                 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
3661         }
3662
3663         if (colormapped)
3664         {
3665                 skinframe->qgeneratebase = false;
3666                 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);
3667                 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);
3668                 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);
3669         }
3670         else
3671         {
3672                 skinframe->qgeneratemerged = false;
3673                 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);
3674         }
3675
3676         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3677         {
3678                 Mem_Free(skinframe->qpixels);
3679                 skinframe->qpixels = NULL;
3680         }
3681 }
3682
3683 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)
3684 {
3685         int i;
3686         skinframe_t *skinframe;
3687         char vabuf[1024];
3688
3689         if (cls.state == ca_dedicated)
3690                 return NULL;
3691
3692         // if already loaded just return it, otherwise make a new skinframe
3693         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3694         if (skinframe && skinframe->base)
3695                 return skinframe;
3696         textureflags &= ~TEXF_FORCE_RELOAD;
3697
3698         skinframe->stain = NULL;
3699         skinframe->merged = NULL;
3700         skinframe->base = NULL;
3701         skinframe->pants = NULL;
3702         skinframe->shirt = NULL;
3703         skinframe->nmap = NULL;
3704         skinframe->gloss = NULL;
3705         skinframe->glow = NULL;
3706         skinframe->fog = NULL;
3707         skinframe->reflect = NULL;
3708         skinframe->hasalpha = false;
3709
3710         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3711         if (!skindata)
3712                 return NULL;
3713
3714         if (developer_loading.integer)
3715                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3716
3717         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3718         if (textureflags & TEXF_ALPHA)
3719         {
3720                 for (i = 0;i < width * height;i++)
3721                 {
3722                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3723                         {
3724                                 skinframe->hasalpha = true;
3725                                 break;
3726                         }
3727                 }
3728                 if (r_loadfog && skinframe->hasalpha)
3729                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3730         }
3731
3732         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3733         //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]);
3734
3735         return skinframe;
3736 }
3737
3738 skinframe_t *R_SkinFrame_LoadMissing(void)
3739 {
3740         skinframe_t *skinframe;
3741
3742         if (cls.state == ca_dedicated)
3743                 return NULL;
3744
3745         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3746         skinframe->stain = NULL;
3747         skinframe->merged = NULL;
3748         skinframe->base = NULL;
3749         skinframe->pants = NULL;
3750         skinframe->shirt = NULL;
3751         skinframe->nmap = NULL;
3752         skinframe->gloss = NULL;
3753         skinframe->glow = NULL;
3754         skinframe->fog = NULL;
3755         skinframe->reflect = NULL;
3756         skinframe->hasalpha = false;
3757
3758         skinframe->avgcolor[0] = rand() / RAND_MAX;
3759         skinframe->avgcolor[1] = rand() / RAND_MAX;
3760         skinframe->avgcolor[2] = rand() / RAND_MAX;
3761         skinframe->avgcolor[3] = 1;
3762
3763         return skinframe;
3764 }
3765
3766 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3767 typedef struct suffixinfo_s
3768 {
3769         const char *suffix;
3770         qboolean flipx, flipy, flipdiagonal;
3771 }
3772 suffixinfo_t;
3773 static suffixinfo_t suffix[3][6] =
3774 {
3775         {
3776                 {"px",   false, false, false},
3777                 {"nx",   false, false, false},
3778                 {"py",   false, false, false},
3779                 {"ny",   false, false, false},
3780                 {"pz",   false, false, false},
3781                 {"nz",   false, false, false}
3782         },
3783         {
3784                 {"posx", false, false, false},
3785                 {"negx", false, false, false},
3786                 {"posy", false, false, false},
3787                 {"negy", false, false, false},
3788                 {"posz", false, false, false},
3789                 {"negz", false, false, false}
3790         },
3791         {
3792                 {"rt",    true, false,  true},
3793                 {"lf",   false,  true,  true},
3794                 {"ft",    true,  true, false},
3795                 {"bk",   false, false, false},
3796                 {"up",    true, false,  true},
3797                 {"dn",    true, false,  true}
3798         }
3799 };
3800
3801 static int componentorder[4] = {0, 1, 2, 3};
3802
3803 static rtexture_t *R_LoadCubemap(const char *basename)
3804 {
3805         int i, j, cubemapsize;
3806         unsigned char *cubemappixels, *image_buffer;
3807         rtexture_t *cubemaptexture;
3808         char name[256];
3809         // must start 0 so the first loadimagepixels has no requested width/height
3810         cubemapsize = 0;
3811         cubemappixels = NULL;
3812         cubemaptexture = NULL;
3813         // keep trying different suffix groups (posx, px, rt) until one loads
3814         for (j = 0;j < 3 && !cubemappixels;j++)
3815         {
3816                 // load the 6 images in the suffix group
3817                 for (i = 0;i < 6;i++)
3818                 {
3819                         // generate an image name based on the base and and suffix
3820                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3821                         // load it
3822                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3823                         {
3824                                 // an image loaded, make sure width and height are equal
3825                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3826                                 {
3827                                         // if this is the first image to load successfully, allocate the cubemap memory
3828                                         if (!cubemappixels && image_width >= 1)
3829                                         {
3830                                                 cubemapsize = image_width;
3831                                                 // note this clears to black, so unavailable sides are black
3832                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3833                                         }
3834                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3835                                         if (cubemappixels)
3836                                                 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);
3837                                 }
3838                                 else
3839                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3840                                 // free the image
3841                                 Mem_Free(image_buffer);
3842                         }
3843                 }
3844         }
3845         // if a cubemap loaded, upload it
3846         if (cubemappixels)
3847         {
3848                 if (developer_loading.integer)
3849                         Con_Printf("loading cubemap \"%s\"\n", basename);
3850
3851                 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);
3852                 Mem_Free(cubemappixels);
3853         }
3854         else
3855         {
3856                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3857                 if (developer_loading.integer)
3858                 {
3859                         Con_Printf("(tried tried images ");
3860                         for (j = 0;j < 3;j++)
3861                                 for (i = 0;i < 6;i++)
3862                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3863                         Con_Print(" and was unable to find any of them).\n");
3864                 }
3865         }
3866         return cubemaptexture;
3867 }
3868
3869 rtexture_t *R_GetCubemap(const char *basename)
3870 {
3871         int i;
3872         for (i = 0;i < r_texture_numcubemaps;i++)
3873                 if (r_texture_cubemaps[i] != NULL)
3874                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3875                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3876         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3877                 return r_texture_whitecube;
3878         r_texture_numcubemaps++;
3879         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3880         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3881         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3882         return r_texture_cubemaps[i]->texture;
3883 }
3884
3885 static void R_Main_FreeViewCache(void)
3886 {
3887         if (r_refdef.viewcache.entityvisible)
3888                 Mem_Free(r_refdef.viewcache.entityvisible);
3889         if (r_refdef.viewcache.world_pvsbits)
3890                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3891         if (r_refdef.viewcache.world_leafvisible)
3892                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3893         if (r_refdef.viewcache.world_surfacevisible)
3894                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3895         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3896 }
3897
3898 static void R_Main_ResizeViewCache(void)
3899 {
3900         int numentities = r_refdef.scene.numentities;
3901         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3902         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3903         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3904         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3905         if (r_refdef.viewcache.maxentities < numentities)
3906         {
3907                 r_refdef.viewcache.maxentities = numentities;
3908                 if (r_refdef.viewcache.entityvisible)
3909                         Mem_Free(r_refdef.viewcache.entityvisible);
3910                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3911         }
3912         if (r_refdef.viewcache.world_numclusters != numclusters)
3913         {
3914                 r_refdef.viewcache.world_numclusters = numclusters;
3915                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3916                 if (r_refdef.viewcache.world_pvsbits)
3917                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3918                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3919         }
3920         if (r_refdef.viewcache.world_numleafs != numleafs)
3921         {
3922                 r_refdef.viewcache.world_numleafs = numleafs;
3923                 if (r_refdef.viewcache.world_leafvisible)
3924                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3925                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3926         }
3927         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3928         {
3929                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3930                 if (r_refdef.viewcache.world_surfacevisible)
3931                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3932                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3933         }
3934 }
3935
3936 extern rtexture_t *loadingscreentexture;
3937 static void gl_main_start(void)
3938 {
3939         loadingscreentexture = NULL;
3940         r_texture_blanknormalmap = NULL;
3941         r_texture_white = NULL;
3942         r_texture_grey128 = NULL;
3943         r_texture_black = NULL;
3944         r_texture_whitecube = NULL;
3945         r_texture_normalizationcube = NULL;
3946         r_texture_fogattenuation = NULL;
3947         r_texture_fogheighttexture = NULL;
3948         r_texture_gammaramps = NULL;
3949         r_texture_numcubemaps = 0;
3950
3951         r_loaddds = r_texture_dds_load.integer != 0;
3952         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3953
3954         switch(vid.renderpath)
3955         {
3956         case RENDERPATH_GL20:
3957         case RENDERPATH_D3D9:
3958         case RENDERPATH_D3D10:
3959         case RENDERPATH_D3D11:
3960         case RENDERPATH_SOFT:
3961         case RENDERPATH_GLES2:
3962                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3963                 Cvar_SetValueQuick(&gl_combine, 1);
3964                 Cvar_SetValueQuick(&r_glsl, 1);
3965                 r_loadnormalmap = true;
3966                 r_loadgloss = true;
3967                 r_loadfog = false;
3968                 break;
3969         case RENDERPATH_GL13:
3970         case RENDERPATH_GLES1:
3971                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3972                 Cvar_SetValueQuick(&gl_combine, 1);
3973                 Cvar_SetValueQuick(&r_glsl, 0);
3974                 r_loadnormalmap = false;
3975                 r_loadgloss = false;
3976                 r_loadfog = true;
3977                 break;
3978         case RENDERPATH_GL11:
3979                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3980                 Cvar_SetValueQuick(&gl_combine, 0);
3981                 Cvar_SetValueQuick(&r_glsl, 0);
3982                 r_loadnormalmap = false;
3983                 r_loadgloss = false;
3984                 r_loadfog = true;
3985                 break;
3986         }
3987
3988         R_AnimCache_Free();
3989         R_FrameData_Reset();
3990
3991         r_numqueries = 0;
3992         r_maxqueries = 0;
3993         memset(r_queries, 0, sizeof(r_queries));
3994
3995         r_qwskincache = NULL;
3996         r_qwskincache_size = 0;
3997
3998         // due to caching of texture_t references, the collision cache must be reset
3999         Collision_Cache_Reset(true);
4000
4001         // set up r_skinframe loading system for textures
4002         memset(&r_skinframe, 0, sizeof(r_skinframe));
4003         r_skinframe.loadsequence = 1;
4004         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4005
4006         r_main_texturepool = R_AllocTexturePool();
4007         R_BuildBlankTextures();
4008         R_BuildNoTexture();
4009         if (vid.support.arb_texture_cube_map)
4010         {
4011                 R_BuildWhiteCube();
4012                 R_BuildNormalizationCube();
4013         }
4014         r_texture_fogattenuation = NULL;
4015         r_texture_fogheighttexture = NULL;
4016         r_texture_gammaramps = NULL;
4017         //r_texture_fogintensity = NULL;
4018         memset(&r_fb, 0, sizeof(r_fb));
4019         r_glsl_permutation = NULL;
4020         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4021         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4022         glslshaderstring = NULL;
4023 #ifdef SUPPORTD3D
4024         r_hlsl_permutation = NULL;
4025         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4026         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4027 #endif
4028         hlslshaderstring = NULL;
4029         memset(&r_svbsp, 0, sizeof (r_svbsp));
4030
4031         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4032         r_texture_numcubemaps = 0;
4033
4034         r_refdef.fogmasktable_density = 0;
4035 }
4036
4037 static void gl_main_shutdown(void)
4038 {
4039         R_AnimCache_Free();
4040         R_FrameData_Reset();
4041
4042         R_Main_FreeViewCache();
4043
4044         switch(vid.renderpath)
4045         {
4046         case RENDERPATH_GL11:
4047         case RENDERPATH_GL13:
4048         case RENDERPATH_GL20:
4049         case RENDERPATH_GLES1:
4050         case RENDERPATH_GLES2:
4051 #ifdef GL_SAMPLES_PASSED_ARB
4052                 if (r_maxqueries)
4053                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4054 #endif
4055                 break;
4056         case RENDERPATH_D3D9:
4057                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4058                 break;
4059         case RENDERPATH_D3D10:
4060                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4061                 break;
4062         case RENDERPATH_D3D11:
4063                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4064                 break;
4065         case RENDERPATH_SOFT:
4066                 break;
4067         }
4068
4069         r_numqueries = 0;
4070         r_maxqueries = 0;
4071         memset(r_queries, 0, sizeof(r_queries));
4072
4073         r_qwskincache = NULL;
4074         r_qwskincache_size = 0;
4075
4076         // clear out the r_skinframe state
4077         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4078         memset(&r_skinframe, 0, sizeof(r_skinframe));
4079
4080         if (r_svbsp.nodes)
4081                 Mem_Free(r_svbsp.nodes);
4082         memset(&r_svbsp, 0, sizeof (r_svbsp));
4083         R_FreeTexturePool(&r_main_texturepool);
4084         loadingscreentexture = NULL;
4085         r_texture_blanknormalmap = NULL;
4086         r_texture_white = NULL;
4087         r_texture_grey128 = NULL;
4088         r_texture_black = NULL;
4089         r_texture_whitecube = NULL;
4090         r_texture_normalizationcube = NULL;
4091         r_texture_fogattenuation = NULL;
4092         r_texture_fogheighttexture = NULL;
4093         r_texture_gammaramps = NULL;
4094         r_texture_numcubemaps = 0;
4095         //r_texture_fogintensity = NULL;
4096         memset(&r_fb, 0, sizeof(r_fb));
4097         R_GLSL_Restart_f();
4098
4099         r_glsl_permutation = NULL;
4100         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4101         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4102         glslshaderstring = NULL;
4103 #ifdef SUPPORTD3D
4104         r_hlsl_permutation = NULL;
4105         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4106         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4107 #endif
4108         hlslshaderstring = NULL;
4109 }
4110
4111 static void gl_main_newmap(void)
4112 {
4113         // FIXME: move this code to client
4114         char *entities, entname[MAX_QPATH];
4115         if (r_qwskincache)
4116                 Mem_Free(r_qwskincache);
4117         r_qwskincache = NULL;
4118         r_qwskincache_size = 0;
4119         if (cl.worldmodel)
4120         {
4121                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4122                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4123                 {
4124                         CL_ParseEntityLump(entities);
4125                         Mem_Free(entities);
4126                         return;
4127                 }
4128                 if (cl.worldmodel->brush.entities)
4129                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4130         }
4131         R_Main_FreeViewCache();
4132
4133         R_FrameData_Reset();
4134 }
4135
4136 void GL_Main_Init(void)
4137 {
4138         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4139
4140         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4141         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4142         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4143         if (gamemode == GAME_NEHAHRA)
4144         {
4145                 Cvar_RegisterVariable (&gl_fogenable);
4146                 Cvar_RegisterVariable (&gl_fogdensity);
4147                 Cvar_RegisterVariable (&gl_fogred);
4148                 Cvar_RegisterVariable (&gl_foggreen);
4149                 Cvar_RegisterVariable (&gl_fogblue);
4150                 Cvar_RegisterVariable (&gl_fogstart);
4151                 Cvar_RegisterVariable (&gl_fogend);
4152                 Cvar_RegisterVariable (&gl_skyclip);
4153         }
4154         Cvar_RegisterVariable(&r_motionblur);
4155         Cvar_RegisterVariable(&r_damageblur);
4156         Cvar_RegisterVariable(&r_motionblur_averaging);
4157         Cvar_RegisterVariable(&r_motionblur_randomize);
4158         Cvar_RegisterVariable(&r_motionblur_minblur);
4159         Cvar_RegisterVariable(&r_motionblur_maxblur);
4160         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4161         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4162         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4163         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4164         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4165         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4166         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4167         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4168         Cvar_RegisterVariable(&r_equalize_entities_by);
4169         Cvar_RegisterVariable(&r_equalize_entities_to);
4170         Cvar_RegisterVariable(&r_depthfirst);
4171         Cvar_RegisterVariable(&r_useinfinitefarclip);
4172         Cvar_RegisterVariable(&r_farclip_base);
4173         Cvar_RegisterVariable(&r_farclip_world);
4174         Cvar_RegisterVariable(&r_nearclip);
4175         Cvar_RegisterVariable(&r_deformvertexes);
4176         Cvar_RegisterVariable(&r_transparent);
4177         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4178         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4179         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4180         Cvar_RegisterVariable(&r_showoverdraw);
4181         Cvar_RegisterVariable(&r_showbboxes);
4182         Cvar_RegisterVariable(&r_showsurfaces);
4183         Cvar_RegisterVariable(&r_showtris);
4184         Cvar_RegisterVariable(&r_shownormals);
4185         Cvar_RegisterVariable(&r_showlighting);
4186         Cvar_RegisterVariable(&r_showshadowvolumes);
4187         Cvar_RegisterVariable(&r_showcollisionbrushes);
4188         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4189         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4190         Cvar_RegisterVariable(&r_showdisabledepthtest);
4191         Cvar_RegisterVariable(&r_drawportals);
4192         Cvar_RegisterVariable(&r_drawentities);
4193         Cvar_RegisterVariable(&r_draw2d);
4194         Cvar_RegisterVariable(&r_drawworld);
4195         Cvar_RegisterVariable(&r_cullentities_trace);
4196         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4197         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4198         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4199         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4200         Cvar_RegisterVariable(&r_sortentities);
4201         Cvar_RegisterVariable(&r_drawviewmodel);
4202         Cvar_RegisterVariable(&r_drawexteriormodel);
4203         Cvar_RegisterVariable(&r_speeds);
4204         Cvar_RegisterVariable(&r_fullbrights);
4205         Cvar_RegisterVariable(&r_wateralpha);
4206         Cvar_RegisterVariable(&r_dynamic);
4207         Cvar_RegisterVariable(&r_fakelight);
4208         Cvar_RegisterVariable(&r_fakelight_intensity);
4209         Cvar_RegisterVariable(&r_fullbright);
4210         Cvar_RegisterVariable(&r_shadows);
4211         Cvar_RegisterVariable(&r_shadows_darken);
4212         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4213         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4214         Cvar_RegisterVariable(&r_shadows_throwdistance);
4215         Cvar_RegisterVariable(&r_shadows_throwdirection);
4216         Cvar_RegisterVariable(&r_shadows_focus);
4217         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4218         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4219         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4220         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4221         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4222         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4223         Cvar_RegisterVariable(&r_fog_exp2);
4224         Cvar_RegisterVariable(&r_fog_clear);
4225         Cvar_RegisterVariable(&r_drawfog);
4226         Cvar_RegisterVariable(&r_transparentdepthmasking);
4227         Cvar_RegisterVariable(&r_transparent_sortmindist);
4228         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4229         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4230         Cvar_RegisterVariable(&r_texture_dds_load);
4231         Cvar_RegisterVariable(&r_texture_dds_save);
4232         Cvar_RegisterVariable(&r_textureunits);
4233         Cvar_RegisterVariable(&gl_combine);
4234         Cvar_RegisterVariable(&r_usedepthtextures);
4235         Cvar_RegisterVariable(&r_viewfbo);
4236         Cvar_RegisterVariable(&r_viewscale);
4237         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4238         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4239         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4240         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4241         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4242         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4243         Cvar_RegisterVariable(&r_glsl);
4244         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4245         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4246         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4247         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4248         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4249         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4250         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4251         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4252         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4253         Cvar_RegisterVariable(&r_glsl_postprocess);
4254         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4255         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4256         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4257         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4258         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4259         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4260         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4261         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4262
4263         Cvar_RegisterVariable(&r_water);
4264         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4265         Cvar_RegisterVariable(&r_water_clippingplanebias);
4266         Cvar_RegisterVariable(&r_water_refractdistort);
4267         Cvar_RegisterVariable(&r_water_reflectdistort);
4268         Cvar_RegisterVariable(&r_water_scissormode);
4269         Cvar_RegisterVariable(&r_water_lowquality);
4270         Cvar_RegisterVariable(&r_water_hideplayer);
4271         Cvar_RegisterVariable(&r_water_fbo);
4272
4273         Cvar_RegisterVariable(&r_lerpsprites);
4274         Cvar_RegisterVariable(&r_lerpmodels);
4275         Cvar_RegisterVariable(&r_lerplightstyles);
4276         Cvar_RegisterVariable(&r_waterscroll);
4277         Cvar_RegisterVariable(&r_bloom);
4278         Cvar_RegisterVariable(&r_bloom_colorscale);
4279         Cvar_RegisterVariable(&r_bloom_brighten);
4280         Cvar_RegisterVariable(&r_bloom_blur);
4281         Cvar_RegisterVariable(&r_bloom_resolution);
4282         Cvar_RegisterVariable(&r_bloom_colorexponent);
4283         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4284         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4285         Cvar_RegisterVariable(&r_hdr_glowintensity);
4286         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4287         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4288         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4289         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4290         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4291         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4292         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4293         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4294         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4295         Cvar_RegisterVariable(&developer_texturelogging);
4296         Cvar_RegisterVariable(&gl_lightmaps);
4297         Cvar_RegisterVariable(&r_test);
4298         Cvar_RegisterVariable(&r_glsl_saturation);
4299         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4300         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4301         Cvar_RegisterVariable(&r_framedatasize);
4302         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4303                 Cvar_SetValue("r_fullbrights", 0);
4304         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4305 }
4306
4307 void Render_Init(void)
4308 {
4309         gl_backend_init();
4310         R_Textures_Init();
4311         GL_Main_Init();
4312         Font_Init();
4313         GL_Draw_Init();
4314         R_Shadow_Init();
4315         R_Sky_Init();
4316         GL_Surf_Init();
4317         Sbar_Init();
4318         R_Particles_Init();
4319         R_Explosion_Init();
4320         R_LightningBeams_Init();
4321         Mod_RenderInit();
4322 }
4323
4324 /*
4325 ===============
4326 GL_Init
4327 ===============
4328 */
4329 #ifndef USE_GLES2
4330 extern char *ENGINE_EXTENSIONS;
4331 void GL_Init (void)
4332 {
4333         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4334         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4335         gl_version = (const char *)qglGetString(GL_VERSION);
4336         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4337
4338         if (!gl_extensions)
4339                 gl_extensions = "";
4340         if (!gl_platformextensions)
4341                 gl_platformextensions = "";
4342
4343         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4344         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4345         Con_Printf("GL_VERSION: %s\n", gl_version);
4346         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4347         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4348
4349         VID_CheckExtensions();
4350
4351         // LordHavoc: report supported extensions
4352         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4353
4354         // clear to black (loading plaque will be seen over this)
4355         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4356 }
4357 #endif
4358
4359 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4360 {
4361         int i;
4362         mplane_t *p;
4363         if (r_trippy.integer)
4364                 return false;
4365         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4366         {
4367                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4368                 if (i == 4)
4369                         continue;
4370                 p = r_refdef.view.frustum + i;
4371                 switch(p->signbits)
4372                 {
4373                 default:
4374                 case 0:
4375                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4376                                 return true;
4377                         break;
4378                 case 1:
4379                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4380                                 return true;
4381                         break;
4382                 case 2:
4383                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4384                                 return true;
4385                         break;
4386                 case 3:
4387                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4388                                 return true;
4389                         break;
4390                 case 4:
4391                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4392                                 return true;
4393                         break;
4394                 case 5:
4395                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4396                                 return true;
4397                         break;
4398                 case 6:
4399                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4400                                 return true;
4401                         break;
4402                 case 7:
4403                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4404                                 return true;
4405                         break;
4406                 }
4407         }
4408         return false;
4409 }
4410
4411 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4412 {
4413         int i;
4414         const mplane_t *p;
4415         if (r_trippy.integer)
4416                 return false;
4417         for (i = 0;i < numplanes;i++)
4418         {
4419                 p = planes + i;
4420                 switch(p->signbits)
4421                 {
4422                 default:
4423                 case 0:
4424                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4425                                 return true;
4426                         break;
4427                 case 1:
4428                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4429                                 return true;
4430                         break;
4431                 case 2:
4432                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4433                                 return true;
4434                         break;
4435                 case 3:
4436                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4437                                 return true;
4438                         break;
4439                 case 4:
4440                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 5:
4444                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 case 6:
4448                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 case 7:
4452                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 }
4456         }
4457         return false;
4458 }
4459
4460 //==================================================================================
4461
4462 // LordHavoc: this stores temporary data used within the same frame
4463
4464 typedef struct r_framedata_mem_s
4465 {
4466         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4467         size_t size; // how much usable space
4468         size_t current; // how much space in use
4469         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4470         size_t wantedsize; // how much space was allocated
4471         unsigned char *data; // start of real data (16byte aligned)
4472 }
4473 r_framedata_mem_t;
4474
4475 static r_framedata_mem_t *r_framedata_mem;
4476
4477 void R_FrameData_Reset(void)
4478 {
4479         while (r_framedata_mem)
4480         {
4481                 r_framedata_mem_t *next = r_framedata_mem->purge;
4482                 Mem_Free(r_framedata_mem);
4483                 r_framedata_mem = next;
4484         }
4485 }
4486
4487 static void R_FrameData_Resize(void)
4488 {
4489         size_t wantedsize;
4490         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4491         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4492         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4493         {
4494                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4495                 newmem->wantedsize = wantedsize;
4496                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4497                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4498                 newmem->current = 0;
4499                 newmem->mark = 0;
4500                 newmem->purge = r_framedata_mem;
4501                 r_framedata_mem = newmem;
4502         }
4503 }
4504
4505 void R_FrameData_NewFrame(void)
4506 {
4507         R_FrameData_Resize();
4508         if (!r_framedata_mem)
4509                 return;
4510         // if we ran out of space on the last frame, free the old memory now
4511         while (r_framedata_mem->purge)
4512         {
4513                 // repeatedly remove the second item in the list, leaving only head
4514                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4515                 Mem_Free(r_framedata_mem->purge);
4516                 r_framedata_mem->purge = next;
4517         }
4518         // reset the current mem pointer
4519         r_framedata_mem->current = 0;
4520         r_framedata_mem->mark = 0;
4521 }
4522
4523 void *R_FrameData_Alloc(size_t size)
4524 {
4525         void *data;
4526
4527         // align to 16 byte boundary - the data pointer is already aligned, so we
4528         // only need to ensure the size of every allocation is also aligned
4529         size = (size + 15) & ~15;
4530
4531         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4532         {
4533                 // emergency - we ran out of space, allocate more memory
4534                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4535                 R_FrameData_Resize();
4536         }
4537
4538         data = r_framedata_mem->data + r_framedata_mem->current;
4539         r_framedata_mem->current += size;
4540
4541         // count the usage for stats
4542         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4543         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4544
4545         return (void *)data;
4546 }
4547
4548 void *R_FrameData_Store(size_t size, void *data)
4549 {
4550         void *d = R_FrameData_Alloc(size);
4551         if (d && data)
4552                 memcpy(d, data, size);
4553         return d;
4554 }
4555
4556 void R_FrameData_SetMark(void)
4557 {
4558         if (!r_framedata_mem)
4559                 return;
4560         r_framedata_mem->mark = r_framedata_mem->current;
4561 }
4562
4563 void R_FrameData_ReturnToMark(void)
4564 {
4565         if (!r_framedata_mem)
4566                 return;
4567         r_framedata_mem->current = r_framedata_mem->mark;
4568 }
4569
4570 //==================================================================================
4571
4572 // LordHavoc: animcache originally written by Echon, rewritten since then
4573
4574 /**
4575  * Animation cache prevents re-generating mesh data for an animated model
4576  * multiple times in one frame for lighting, shadowing, reflections, etc.
4577  */
4578
4579 void R_AnimCache_Free(void)
4580 {
4581 }
4582
4583 void R_AnimCache_ClearCache(void)
4584 {
4585         int i;
4586         entity_render_t *ent;
4587
4588         for (i = 0;i < r_refdef.scene.numentities;i++)
4589         {
4590                 ent = r_refdef.scene.entities[i];
4591                 ent->animcache_vertex3f = NULL;
4592                 ent->animcache_normal3f = NULL;
4593                 ent->animcache_svector3f = NULL;
4594                 ent->animcache_tvector3f = NULL;
4595                 ent->animcache_vertexmesh = NULL;
4596                 ent->animcache_vertex3fbuffer = NULL;
4597                 ent->animcache_vertexmeshbuffer = NULL;
4598         }
4599 }
4600
4601 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4602 {
4603         int i;
4604
4605         // check if we need the meshbuffers
4606         if (!vid.useinterleavedarrays)
4607                 return;
4608
4609         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4610                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4611         // TODO: upload vertex3f buffer?
4612         if (ent->animcache_vertexmesh)
4613         {
4614                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4615                 for (i = 0;i < numvertices;i++)
4616                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4617                 if (ent->animcache_svector3f)
4618                         for (i = 0;i < numvertices;i++)
4619                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4620                 if (ent->animcache_tvector3f)
4621                         for (i = 0;i < numvertices;i++)
4622                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4623                 if (ent->animcache_normal3f)
4624                         for (i = 0;i < numvertices;i++)
4625                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4626                 // TODO: upload vertexmeshbuffer?
4627         }
4628 }
4629
4630 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4631 {
4632         dp_model_t *model = ent->model;
4633         int numvertices;
4634         // see if it's already cached this frame
4635         if (ent->animcache_vertex3f)
4636         {
4637                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4638                 if (wantnormals || wanttangents)
4639                 {
4640                         if (ent->animcache_normal3f)
4641                                 wantnormals = false;
4642                         if (ent->animcache_svector3f)
4643                                 wanttangents = false;
4644                         if (wantnormals || wanttangents)
4645                         {
4646                                 numvertices = model->surfmesh.num_vertices;
4647                                 if (wantnormals)
4648                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4649                                 if (wanttangents)
4650                                 {
4651                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4652                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4653                                 }
4654                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4655                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4656                         }
4657                 }
4658         }
4659         else
4660         {
4661                 // see if this ent is worth caching
4662                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4663                         return false;
4664                 // get some memory for this entity and generate mesh data
4665                 numvertices = model->surfmesh.num_vertices;
4666                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
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, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4675                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4676         }
4677         return true;
4678 }
4679
4680 void R_AnimCache_CacheVisibleEntities(void)
4681 {
4682         int i;
4683         qboolean wantnormals = true;
4684         qboolean wanttangents = !r_showsurfaces.integer;
4685
4686         switch(vid.renderpath)
4687         {
4688         case RENDERPATH_GL20:
4689         case RENDERPATH_D3D9:
4690         case RENDERPATH_D3D10:
4691         case RENDERPATH_D3D11:
4692         case RENDERPATH_GLES2:
4693                 break;
4694         case RENDERPATH_GL11:
4695         case RENDERPATH_GL13:
4696         case RENDERPATH_GLES1:
4697                 wanttangents = false;
4698                 break;
4699         case RENDERPATH_SOFT:
4700                 break;
4701         }
4702
4703         if (r_shownormals.integer)
4704                 wanttangents = wantnormals = true;
4705
4706         // TODO: thread this
4707         // NOTE: R_PrepareRTLights() also caches entities
4708
4709         for (i = 0;i < r_refdef.scene.numentities;i++)
4710                 if (r_refdef.viewcache.entityvisible[i])
4711                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4712 }
4713
4714 //==================================================================================
4715
4716 extern cvar_t r_overheadsprites_pushback;
4717
4718 static void R_View_UpdateEntityLighting (void)
4719 {
4720         int i;
4721         entity_render_t *ent;
4722         vec3_t tempdiffusenormal, avg;
4723         vec_t f, fa, fd, fdd;
4724         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4725
4726         for (i = 0;i < r_refdef.scene.numentities;i++)
4727         {
4728                 ent = r_refdef.scene.entities[i];
4729
4730                 // skip unseen models and models that updated by CSQC
4731                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4732                         continue;
4733
4734                 // skip bsp models
4735                 if (ent->model && (ent->model == cl.worldmodel || ent->model->brush.parentmodel == cl.worldmodel))
4736                 {
4737                         // TODO: use modellight for r_ambient settings on world?
4738                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4739                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4740                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4741                         continue;
4742                 }
4743
4744                 // fetch the lighting from the worldmodel data
4745                 VectorClear(ent->modellight_ambient);
4746                 VectorClear(ent->modellight_diffuse);
4747                 VectorClear(tempdiffusenormal);
4748                 if (ent->flags & RENDER_LIGHT)
4749                 {
4750                         vec3_t org;
4751                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4752
4753                         // complete lightning for lit sprites
4754                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4755                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4756                         {
4757                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4758                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4759                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4760                         }
4761                         else
4762                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4763
4764                         if(ent->flags & RENDER_EQUALIZE)
4765                         {
4766                                 // first fix up ambient lighting...
4767                                 if(r_equalize_entities_minambient.value > 0)
4768                                 {
4769                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4770                                         if(fd > 0)
4771                                         {
4772                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4773                                                 if(fa < r_equalize_entities_minambient.value * fd)
4774                                                 {
4775                                                         // solve:
4776                                                         //   fa'/fd' = minambient
4777                                                         //   fa'+0.25*fd' = fa+0.25*fd
4778                                                         //   ...
4779                                                         //   fa' = fd' * minambient
4780                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4781                                                         //   ...
4782                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4783                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4784                                                         //   ...
4785                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4786                                                         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
4787                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4788                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4789                                                 }
4790                                         }
4791                                 }
4792
4793                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4794                                 {
4795                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4796                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4797                                         f = fa + 0.25 * fd;
4798                                         if(f > 0)
4799                                         {
4800                                                 // adjust brightness and saturation to target
4801                                                 avg[0] = avg[1] = avg[2] = fa / f;
4802                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4803                                                 avg[0] = avg[1] = avg[2] = fd / f;
4804                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4805                                         }
4806                                 }
4807                         }
4808                 }
4809                 else // highly rare
4810                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4811
4812                 // move the light direction into modelspace coordinates for lighting code
4813                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4814                 if(VectorLength2(ent->modellight_lightdir) == 0)
4815                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4816                 VectorNormalize(ent->modellight_lightdir);
4817         }
4818 }
4819
4820 #define MAX_LINEOFSIGHTTRACES 64
4821
4822 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4823 {
4824         int i;
4825         vec3_t boxmins, boxmaxs;
4826         vec3_t start;
4827         vec3_t end;
4828         dp_model_t *model = r_refdef.scene.worldmodel;
4829
4830         if (!model || !model->brush.TraceLineOfSight)
4831                 return true;
4832
4833         // expand the box a little
4834         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4835         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4836         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4837         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4838         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4839         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4840
4841         // return true if eye is inside enlarged box
4842         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4843                 return true;
4844
4845         // try center
4846         VectorCopy(eye, start);
4847         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4848         if (model->brush.TraceLineOfSight(model, start, end))
4849                 return true;
4850
4851         // try various random positions
4852         for (i = 0;i < numsamples;i++)
4853         {
4854                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4855                 if (model->brush.TraceLineOfSight(model, start, end))
4856                         return true;
4857         }
4858
4859         return false;
4860 }
4861
4862
4863 static void R_View_UpdateEntityVisible (void)
4864 {
4865         int i;
4866         int renderimask;
4867         int samples;
4868         entity_render_t *ent;
4869
4870         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4871                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4872                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4873                 :                                                          RENDER_EXTERIORMODEL;
4874         if (!r_drawviewmodel.integer)
4875                 renderimask |= RENDER_VIEWMODEL;
4876         if (!r_drawexteriormodel.integer)
4877                 renderimask |= RENDER_EXTERIORMODEL;
4878         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4879         {
4880                 // worldmodel can check visibility
4881                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4882                 for (i = 0;i < r_refdef.scene.numentities;i++)
4883                 {
4884                         ent = r_refdef.scene.entities[i];
4885                         if (!(ent->flags & renderimask))
4886                         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)))
4887                         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))
4888                                 r_refdef.viewcache.entityvisible[i] = true;
4889                 }
4890         }
4891         else
4892         {
4893                 // no worldmodel or it can't check visibility
4894                 for (i = 0;i < r_refdef.scene.numentities;i++)
4895                 {
4896                         ent = r_refdef.scene.entities[i];
4897                         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));
4898                 }
4899         }
4900         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4901                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4902         {
4903                 for (i = 0;i < r_refdef.scene.numentities;i++)
4904                 {
4905                         if (!r_refdef.viewcache.entityvisible[i])
4906                                 continue;
4907                         ent = r_refdef.scene.entities[i];
4908                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4909                         {
4910                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4911                                 if (samples < 0)
4912                                         continue; // temp entities do pvs only
4913                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4914                                         ent->last_trace_visibility = realtime;
4915                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4916                                         r_refdef.viewcache.entityvisible[i] = 0;
4917                         }
4918                 }
4919         }
4920 }
4921
4922 /// only used if skyrendermasked, and normally returns false
4923 static int R_DrawBrushModelsSky (void)
4924 {
4925         int i, sky;
4926         entity_render_t *ent;
4927
4928         sky = false;
4929         for (i = 0;i < r_refdef.scene.numentities;i++)
4930         {
4931                 if (!r_refdef.viewcache.entityvisible[i])
4932                         continue;
4933                 ent = r_refdef.scene.entities[i];
4934                 if (!ent->model || !ent->model->DrawSky)
4935                         continue;
4936                 ent->model->DrawSky(ent);
4937                 sky = true;
4938         }
4939         return sky;
4940 }
4941
4942 static void R_DrawNoModel(entity_render_t *ent);
4943 static void R_DrawModels(void)
4944 {
4945         int i;
4946         entity_render_t *ent;
4947
4948         for (i = 0;i < r_refdef.scene.numentities;i++)
4949         {
4950                 if (!r_refdef.viewcache.entityvisible[i])
4951                         continue;
4952                 ent = r_refdef.scene.entities[i];
4953                 r_refdef.stats.entities++;
4954                 /*
4955                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4956                 {
4957                         vec3_t f, l, u, o;
4958                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4959                         Con_Printf("R_DrawModels\n");
4960                         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]);
4961                         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);
4962                         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);
4963                 }
4964                 */
4965                 if (ent->model && ent->model->Draw != NULL)
4966                         ent->model->Draw(ent);
4967                 else
4968                         R_DrawNoModel(ent);
4969         }
4970 }
4971
4972 static void R_DrawModelsDepth(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                 if (ent->model && ent->model->DrawDepth != NULL)
4983                         ent->model->DrawDepth(ent);
4984         }
4985 }
4986
4987 static void R_DrawModelsDebug(void)
4988 {
4989         int i;
4990         entity_render_t *ent;
4991
4992         for (i = 0;i < r_refdef.scene.numentities;i++)
4993         {
4994                 if (!r_refdef.viewcache.entityvisible[i])
4995                         continue;
4996                 ent = r_refdef.scene.entities[i];
4997                 if (ent->model && ent->model->DrawDebug != NULL)
4998                         ent->model->DrawDebug(ent);
4999         }
5000 }
5001
5002 static void R_DrawModelsAddWaterPlanes(void)
5003 {
5004         int i;
5005         entity_render_t *ent;
5006
5007         for (i = 0;i < r_refdef.scene.numentities;i++)
5008         {
5009                 if (!r_refdef.viewcache.entityvisible[i])
5010                         continue;
5011                 ent = r_refdef.scene.entities[i];
5012                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5013                         ent->model->DrawAddWaterPlanes(ent);
5014         }
5015 }
5016
5017 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}};
5018
5019 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5020 {
5021         if (r_hdr_irisadaptation.integer)
5022         {
5023                 vec3_t p;
5024                 vec3_t ambient;
5025                 vec3_t diffuse;
5026                 vec3_t diffusenormal;
5027                 vec3_t forward;
5028                 vec_t brightness = 0.0f;
5029                 vec_t goal;
5030                 vec_t current;
5031                 vec_t d;
5032                 int c;
5033                 VectorCopy(r_refdef.view.forward, forward);
5034                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5035                 {
5036                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5037                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5038                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5039                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5040                         d = DotProduct(forward, diffusenormal);
5041                         brightness += VectorLength(ambient);
5042                         if (d > 0)
5043                                 brightness += d * VectorLength(diffuse);
5044                 }
5045                 brightness *= 1.0f / c;
5046                 brightness += 0.00001f; // make sure it's never zero
5047                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5048                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5049                 current = r_hdr_irisadaptation_value.value;
5050                 if (current < goal)
5051                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5052                 else if (current > goal)
5053                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5054                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5055                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5056         }
5057         else if (r_hdr_irisadaptation_value.value != 1.0f)
5058                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5059 }
5060
5061 static void R_View_SetFrustum(const int *scissor)
5062 {
5063         int i;
5064         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5065         vec3_t forward, left, up, origin, v;
5066
5067         if(scissor)
5068         {
5069                 // flipped x coordinates (because x points left here)
5070                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5071                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5072
5073                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5074                 switch(vid.renderpath)
5075                 {
5076                         case RENDERPATH_D3D9:
5077                         case RENDERPATH_D3D10:
5078                         case RENDERPATH_D3D11:
5079                                 // non-flipped y coordinates
5080                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5081                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5082                                 break;
5083                         case RENDERPATH_SOFT:
5084                         case RENDERPATH_GL11:
5085                         case RENDERPATH_GL13:
5086                         case RENDERPATH_GL20:
5087                         case RENDERPATH_GLES1:
5088                         case RENDERPATH_GLES2:
5089                                 // non-flipped y coordinates
5090                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5091                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5092                                 break;
5093                 }
5094         }
5095
5096         // we can't trust r_refdef.view.forward and friends in reflected scenes
5097         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5098
5099 #if 0
5100         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5101         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5102         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5103         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5104         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5105         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5106         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5107         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5108         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5109         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5110         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5111         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5112 #endif
5113
5114 #if 0
5115         zNear = r_refdef.nearclip;
5116         nudge = 1.0 - 1.0 / (1<<23);
5117         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5118         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5119         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5120         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5121         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5122         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5123         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5124         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5125 #endif
5126
5127
5128
5129 #if 0
5130         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5131         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5132         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5133         r_refdef.view.frustum[0].dist = m[15] - m[12];
5134
5135         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5136         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5137         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5138         r_refdef.view.frustum[1].dist = m[15] + m[12];
5139
5140         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5141         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5142         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5143         r_refdef.view.frustum[2].dist = m[15] - m[13];
5144
5145         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5146         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5147         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5148         r_refdef.view.frustum[3].dist = m[15] + m[13];
5149
5150         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5151         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5152         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5153         r_refdef.view.frustum[4].dist = m[15] - m[14];
5154
5155         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5156         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5157         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5158         r_refdef.view.frustum[5].dist = m[15] + m[14];
5159 #endif
5160
5161         if (r_refdef.view.useperspective)
5162         {
5163                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5164                 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]);
5165                 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]);
5166                 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]);
5167                 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]);
5168
5169                 // then the normals from the corners relative to origin
5170                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5171                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5172                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5173                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5174
5175                 // in a NORMAL view, forward cross left == up
5176                 // in a REFLECTED view, forward cross left == down
5177                 // so our cross products above need to be adjusted for a left handed coordinate system
5178                 CrossProduct(forward, left, v);
5179                 if(DotProduct(v, up) < 0)
5180                 {
5181                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5182                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5183                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5184                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5185                 }
5186
5187                 // Leaving those out was a mistake, those were in the old code, and they
5188                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5189                 // I couldn't reproduce it after adding those normalizations. --blub
5190                 VectorNormalize(r_refdef.view.frustum[0].normal);
5191                 VectorNormalize(r_refdef.view.frustum[1].normal);
5192                 VectorNormalize(r_refdef.view.frustum[2].normal);
5193                 VectorNormalize(r_refdef.view.frustum[3].normal);
5194
5195                 // make the corners absolute
5196                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5197                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5198                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5199                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5200
5201                 // one more normal
5202                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5203
5204                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5205                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5206                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5207                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5208                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5209         }
5210         else
5211         {
5212                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5213                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5214                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5215                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5216                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5217                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5218                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5219                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5220                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5221                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5222         }
5223         r_refdef.view.numfrustumplanes = 5;
5224
5225         if (r_refdef.view.useclipplane)
5226         {
5227                 r_refdef.view.numfrustumplanes = 6;
5228                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5229         }
5230
5231         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5232                 PlaneClassify(r_refdef.view.frustum + i);
5233
5234         // LordHavoc: note to all quake engine coders, Quake had a special case
5235         // for 90 degrees which assumed a square view (wrong), so I removed it,
5236         // Quake2 has it disabled as well.
5237
5238         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5239         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5240         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5241         //PlaneClassify(&frustum[0]);
5242
5243         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5244         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5245         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5246         //PlaneClassify(&frustum[1]);
5247
5248         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5249         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5250         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5251         //PlaneClassify(&frustum[2]);
5252
5253         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5254         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5255         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5256         //PlaneClassify(&frustum[3]);
5257
5258         // nearclip plane
5259         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5260         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5261         //PlaneClassify(&frustum[4]);
5262 }
5263
5264 static void R_View_UpdateWithScissor(const int *myscissor)
5265 {
5266         R_Main_ResizeViewCache();
5267         R_View_SetFrustum(myscissor);
5268         R_View_WorldVisibility(r_refdef.view.useclipplane);
5269         R_View_UpdateEntityVisible();
5270         R_View_UpdateEntityLighting();
5271         R_AnimCache_CacheVisibleEntities();
5272 }
5273
5274 static void R_View_Update(void)
5275 {
5276         R_Main_ResizeViewCache();
5277         R_View_SetFrustum(NULL);
5278         R_View_WorldVisibility(r_refdef.view.useclipplane);
5279         R_View_UpdateEntityVisible();
5280         R_View_UpdateEntityLighting();
5281         R_AnimCache_CacheVisibleEntities();
5282 }
5283
5284 float viewscalefpsadjusted = 1.0f;
5285
5286 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5287 {
5288         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5289         scale = bound(0.03125f, scale, 1.0f);
5290         *outwidth = (int)ceil(width * scale);
5291         *outheight = (int)ceil(height * scale);
5292 }
5293
5294 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5295 {
5296         const float *customclipplane = NULL;
5297         float plane[4];
5298         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5299         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5300         {
5301                 // LordHavoc: couldn't figure out how to make this approach the
5302                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5303                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5304                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5305                         dist = r_refdef.view.clipplane.dist;
5306                 plane[0] = r_refdef.view.clipplane.normal[0];
5307                 plane[1] = r_refdef.view.clipplane.normal[1];
5308                 plane[2] = r_refdef.view.clipplane.normal[2];
5309                 plane[3] = -dist;
5310                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5311         }
5312
5313         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5314         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5315
5316         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5317         if (!r_refdef.view.useperspective)
5318                 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);
5319         else if (vid.stencil && r_useinfinitefarclip.integer)
5320                 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);
5321         else
5322                 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);
5323         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5324         R_SetViewport(&r_refdef.view.viewport);
5325         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5326         {
5327                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5328                 float screenplane[4];
5329                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5330                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5331                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5332                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5333                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5334         }
5335 }
5336
5337 void R_EntityMatrix(const matrix4x4_t *matrix)
5338 {
5339         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5340         {
5341                 gl_modelmatrixchanged = false;
5342                 gl_modelmatrix = *matrix;
5343                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5344                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5345                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5346                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5347                 CHECKGLERROR
5348                 switch(vid.renderpath)
5349                 {
5350                 case RENDERPATH_D3D9:
5351 #ifdef SUPPORTD3D
5352                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5353                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5354 #endif
5355                         break;
5356                 case RENDERPATH_D3D10:
5357                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5358                         break;
5359                 case RENDERPATH_D3D11:
5360                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5361                         break;
5362                 case RENDERPATH_GL11:
5363                 case RENDERPATH_GL13:
5364                 case RENDERPATH_GLES1:
5365                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5366                         break;
5367                 case RENDERPATH_SOFT:
5368                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5369                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5370                         break;
5371                 case RENDERPATH_GL20:
5372                 case RENDERPATH_GLES2:
5373                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5374                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5375                         break;
5376                 }
5377         }
5378 }
5379
5380 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5381 {
5382         r_viewport_t viewport;
5383
5384         CHECKGLERROR
5385
5386         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5387         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);
5388         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5389         R_SetViewport(&viewport);
5390         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5391         GL_Color(1, 1, 1, 1);
5392         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5393         GL_BlendFunc(GL_ONE, GL_ZERO);
5394         GL_ScissorTest(false);
5395         GL_DepthMask(false);
5396         GL_DepthRange(0, 1);
5397         GL_DepthTest(false);
5398         GL_DepthFunc(GL_LEQUAL);
5399         R_EntityMatrix(&identitymatrix);
5400         R_Mesh_ResetTextureState();
5401         GL_PolygonOffset(0, 0);
5402         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5403         switch(vid.renderpath)
5404         {
5405         case RENDERPATH_GL11:
5406         case RENDERPATH_GL13:
5407         case RENDERPATH_GL20:
5408         case RENDERPATH_GLES1:
5409         case RENDERPATH_GLES2:
5410                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5411                 break;
5412         case RENDERPATH_D3D9:
5413         case RENDERPATH_D3D10:
5414         case RENDERPATH_D3D11:
5415         case RENDERPATH_SOFT:
5416                 break;
5417         }
5418         GL_CullFace(GL_NONE);
5419
5420         CHECKGLERROR
5421 }
5422
5423 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5424 {
5425         DrawQ_Finish();
5426
5427         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5428 }
5429
5430 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5431 {
5432         DrawQ_Finish();
5433
5434         R_SetupView(true, fbo, depthtexture, colortexture);
5435         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5436         GL_Color(1, 1, 1, 1);
5437         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5438         GL_BlendFunc(GL_ONE, GL_ZERO);
5439         GL_ScissorTest(true);
5440         GL_DepthMask(true);
5441         GL_DepthRange(0, 1);
5442         GL_DepthTest(true);
5443         GL_DepthFunc(GL_LEQUAL);
5444         R_EntityMatrix(&identitymatrix);
5445         R_Mesh_ResetTextureState();
5446         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5447         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5448         switch(vid.renderpath)
5449         {
5450         case RENDERPATH_GL11:
5451         case RENDERPATH_GL13:
5452         case RENDERPATH_GL20:
5453         case RENDERPATH_GLES1:
5454         case RENDERPATH_GLES2:
5455                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5456                 break;
5457         case RENDERPATH_D3D9:
5458         case RENDERPATH_D3D10:
5459         case RENDERPATH_D3D11:
5460         case RENDERPATH_SOFT:
5461                 break;
5462         }
5463         GL_CullFace(r_refdef.view.cullface_back);
5464 }
5465
5466 /*
5467 ================
5468 R_RenderView_UpdateViewVectors
5469 ================
5470 */
5471 void R_RenderView_UpdateViewVectors(void)
5472 {
5473         // break apart the view matrix into vectors for various purposes
5474         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5475         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5476         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5477         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5478         // make an inverted copy of the view matrix for tracking sprites
5479         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5480 }
5481
5482 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5483 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5484
5485 static void R_Water_StartFrame(void)
5486 {
5487         int i;
5488         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5489         r_waterstate_waterplane_t *p;
5490         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5491
5492         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5493                 return;
5494
5495         switch(vid.renderpath)
5496         {
5497         case RENDERPATH_GL20:
5498         case RENDERPATH_D3D9:
5499         case RENDERPATH_D3D10:
5500         case RENDERPATH_D3D11:
5501         case RENDERPATH_SOFT:
5502         case RENDERPATH_GLES2:
5503                 break;
5504         case RENDERPATH_GL11:
5505         case RENDERPATH_GL13:
5506         case RENDERPATH_GLES1:
5507                 return;
5508         }
5509
5510         // set waterwidth and waterheight to the water resolution that will be
5511         // used (often less than the screen resolution for faster rendering)
5512         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5513
5514         // calculate desired texture sizes
5515         // can't use water if the card does not support the texture size
5516         if (!r_water.integer || r_showsurfaces.integer)
5517                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5518         else if (vid.support.arb_texture_non_power_of_two)
5519         {
5520                 texturewidth = waterwidth;
5521                 textureheight = waterheight;
5522                 camerawidth = waterwidth;
5523                 cameraheight = waterheight;
5524         }
5525         else
5526         {
5527                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5528                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5529                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5530                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5531         }
5532
5533         // allocate textures as needed
5534         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))
5535         {
5536                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5537                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5538                 {
5539                         if (p->texture_refraction)
5540                                 R_FreeTexture(p->texture_refraction);
5541                         p->texture_refraction = NULL;
5542                         if (p->fbo_refraction)
5543                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5544                         p->fbo_refraction = 0;
5545                         if (p->texture_reflection)
5546                                 R_FreeTexture(p->texture_reflection);
5547                         p->texture_reflection = NULL;
5548                         if (p->fbo_reflection)
5549                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5550                         p->fbo_reflection = 0;
5551                         if (p->texture_camera)
5552                                 R_FreeTexture(p->texture_camera);
5553                         p->texture_camera = NULL;
5554                         if (p->fbo_camera)
5555                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5556                         p->fbo_camera = 0;
5557                 }
5558                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5559                 r_fb.water.texturewidth = texturewidth;
5560                 r_fb.water.textureheight = textureheight;
5561                 r_fb.water.camerawidth = camerawidth;
5562                 r_fb.water.cameraheight = cameraheight;
5563         }
5564
5565         if (r_fb.water.texturewidth)
5566         {
5567                 int scaledwidth, scaledheight;
5568
5569                 r_fb.water.enabled = true;
5570
5571                 // water resolution is usually reduced
5572                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5573                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5574                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5575
5576                 // set up variables that will be used in shader setup
5577                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5578                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5579                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5580                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5581         }
5582
5583         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5584         r_fb.water.numwaterplanes = 0;
5585 }
5586
5587 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5588 {
5589         int planeindex, bestplaneindex, vertexindex;
5590         vec3_t mins, maxs, normal, center, v, n;
5591         vec_t planescore, bestplanescore;
5592         mplane_t plane;
5593         r_waterstate_waterplane_t *p;
5594         texture_t *t = R_GetCurrentTexture(surface->texture);
5595
5596         rsurface.texture = t;
5597         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5598         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5599         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5600                 return;
5601         // average the vertex normals, find the surface bounds (after deformvertexes)
5602         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5603         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5604         VectorCopy(n, normal);
5605         VectorCopy(v, mins);
5606         VectorCopy(v, maxs);
5607         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5608         {
5609                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5610                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5611                 VectorAdd(normal, n, normal);
5612                 mins[0] = min(mins[0], v[0]);
5613                 mins[1] = min(mins[1], v[1]);
5614                 mins[2] = min(mins[2], v[2]);
5615                 maxs[0] = max(maxs[0], v[0]);
5616                 maxs[1] = max(maxs[1], v[1]);
5617                 maxs[2] = max(maxs[2], v[2]);
5618         }
5619         VectorNormalize(normal);
5620         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5621
5622         VectorCopy(normal, plane.normal);
5623         VectorNormalize(plane.normal);
5624         plane.dist = DotProduct(center, plane.normal);
5625         PlaneClassify(&plane);
5626         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5627         {
5628                 // skip backfaces (except if nocullface is set)
5629 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5630 //                      return;
5631                 VectorNegate(plane.normal, plane.normal);
5632                 plane.dist *= -1;
5633                 PlaneClassify(&plane);
5634         }
5635
5636
5637         // find a matching plane if there is one
5638         bestplaneindex = -1;
5639         bestplanescore = 1048576.0f;
5640         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5641         {
5642                 if(p->camera_entity == t->camera_entity)
5643                 {
5644                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5645                         if (bestplaneindex < 0 || bestplanescore > planescore)
5646                         {
5647                                 bestplaneindex = planeindex;
5648                                 bestplanescore = planescore;
5649                         }
5650                 }
5651         }
5652         planeindex = bestplaneindex;
5653         p = r_fb.water.waterplanes + planeindex;
5654
5655         // if this surface does not fit any known plane rendered this frame, add one
5656         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5657         {
5658                 // store the new plane
5659                 planeindex = r_fb.water.numwaterplanes++;
5660                 p = r_fb.water.waterplanes + planeindex;
5661                 p->plane = plane;
5662                 // clear materialflags and pvs
5663                 p->materialflags = 0;
5664                 p->pvsvalid = false;
5665                 p->camera_entity = t->camera_entity;
5666                 VectorCopy(mins, p->mins);
5667                 VectorCopy(maxs, p->maxs);
5668         }
5669         else
5670         {
5671                 // merge mins/maxs when we're adding this surface to the plane
5672                 p->mins[0] = min(p->mins[0], mins[0]);
5673                 p->mins[1] = min(p->mins[1], mins[1]);
5674                 p->mins[2] = min(p->mins[2], mins[2]);
5675                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5676                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5677                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5678         }
5679         // merge this surface's materialflags into the waterplane
5680         p->materialflags |= t->currentmaterialflags;
5681         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5682         {
5683                 // merge this surface's PVS into the waterplane
5684                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5685                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5686                 {
5687                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5688                         p->pvsvalid = true;
5689                 }
5690         }
5691 }
5692
5693 extern cvar_t r_drawparticles;
5694 extern cvar_t r_drawdecals;
5695
5696 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5697 {
5698         int myscissor[4];
5699         r_refdef_view_t originalview;
5700         r_refdef_view_t myview;
5701         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;
5702         r_waterstate_waterplane_t *p;
5703         vec3_t visorigin;
5704         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5705         char vabuf[1024];
5706
5707         originalview = r_refdef.view;
5708
5709         // lowquality hack, temporarily shut down some cvars and restore afterwards
5710         qualityreduction = r_water_lowquality.integer;
5711         if (qualityreduction > 0)
5712         {
5713                 if (qualityreduction >= 1)
5714                 {
5715                         old_r_shadows = r_shadows.integer;
5716                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5717                         old_r_dlight = r_shadow_realtime_dlight.integer;
5718                         Cvar_SetValueQuick(&r_shadows, 0);
5719                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5720                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5721                 }
5722                 if (qualityreduction >= 2)
5723                 {
5724                         old_r_dynamic = r_dynamic.integer;
5725                         old_r_particles = r_drawparticles.integer;
5726                         old_r_decals = r_drawdecals.integer;
5727                         Cvar_SetValueQuick(&r_dynamic, 0);
5728                         Cvar_SetValueQuick(&r_drawparticles, 0);
5729                         Cvar_SetValueQuick(&r_drawdecals, 0);
5730                 }
5731         }
5732
5733         // make sure enough textures are allocated
5734         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5735         {
5736                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5737                 {
5738                         if (!p->texture_refraction)
5739                                 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);
5740                         if (!p->texture_refraction)
5741                                 goto error;
5742                         if (usewaterfbo)
5743                         {
5744                                 if (r_fb.water.depthtexture == NULL)
5745                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5746                                 if (p->fbo_refraction == 0)
5747                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5748                         }
5749                 }
5750                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5751                 {
5752                         if (!p->texture_camera)
5753                                 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);
5754                         if (!p->texture_camera)
5755                                 goto error;
5756                         if (usewaterfbo)
5757                         {
5758                                 if (r_fb.water.depthtexture == NULL)
5759                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5760                                 if (p->fbo_camera == 0)
5761                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5762                         }
5763                 }
5764
5765                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5766                 {
5767                         if (!p->texture_reflection)
5768                                 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);
5769                         if (!p->texture_reflection)
5770                                 goto error;
5771                         if (usewaterfbo)
5772                         {
5773                                 if (r_fb.water.depthtexture == NULL)
5774                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5775                                 if (p->fbo_reflection == 0)
5776                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5777                         }
5778                 }
5779         }
5780
5781         // render views
5782         r_refdef.view = originalview;
5783         r_refdef.view.showdebug = false;
5784         r_refdef.view.width = r_fb.water.waterwidth;
5785         r_refdef.view.height = r_fb.water.waterheight;
5786         r_refdef.view.useclipplane = true;
5787         myview = r_refdef.view;
5788         r_fb.water.renderingscene = true;
5789         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5790         {
5791                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5792                 {
5793                         r_refdef.view = myview;
5794                         if(r_water_scissormode.integer)
5795                         {
5796                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5797                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5798                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5799                         }
5800
5801                         // render reflected scene and copy into texture
5802                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5803                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5804                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5805                         r_refdef.view.clipplane = p->plane;
5806                         // reverse the cullface settings for this render
5807                         r_refdef.view.cullface_front = GL_FRONT;
5808                         r_refdef.view.cullface_back = GL_BACK;
5809                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5810                         {
5811                                 r_refdef.view.usecustompvs = true;
5812                                 if (p->pvsvalid)
5813                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5814                                 else
5815                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5816                         }
5817
5818                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5819                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5820                         R_ClearScreen(r_refdef.fogenabled);
5821                         if(r_water_scissormode.integer & 2)
5822                                 R_View_UpdateWithScissor(myscissor);
5823                         else
5824                                 R_View_Update();
5825                         if(r_water_scissormode.integer & 1)
5826                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5827                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5828
5829                         if (!p->fbo_reflection)
5830                                 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);
5831                         r_fb.water.hideplayer = false;
5832                 }
5833
5834                 // render the normal view scene and copy into texture
5835                 // (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)
5836                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5837                 {
5838                         r_refdef.view = myview;
5839                         if(r_water_scissormode.integer)
5840                         {
5841                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5842                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5843                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5844                         }
5845
5846                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5847
5848                         r_refdef.view.clipplane = p->plane;
5849                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5850                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5851
5852                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5853                         {
5854                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5855                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5856                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5857                                 R_RenderView_UpdateViewVectors();
5858                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5859                                 {
5860                                         r_refdef.view.usecustompvs = true;
5861                                         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);
5862                                 }
5863                         }
5864
5865                         PlaneClassify(&r_refdef.view.clipplane);
5866
5867                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5868                         R_ClearScreen(r_refdef.fogenabled);
5869                         if(r_water_scissormode.integer & 2)
5870                                 R_View_UpdateWithScissor(myscissor);
5871                         else
5872                                 R_View_Update();
5873                         if(r_water_scissormode.integer & 1)
5874                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5875                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5876
5877                         if (!p->fbo_refraction)
5878                                 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);
5879                         r_fb.water.hideplayer = false;
5880                 }
5881                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5882                 {
5883                         r_refdef.view = myview;
5884
5885                         r_refdef.view.clipplane = p->plane;
5886                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5887                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5888
5889                         r_refdef.view.width = r_fb.water.camerawidth;
5890                         r_refdef.view.height = r_fb.water.cameraheight;
5891                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5892                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5893                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5894                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5895
5896                         if(p->camera_entity)
5897                         {
5898                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5899                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5900                         }
5901
5902                         // note: all of the view is used for displaying... so
5903                         // there is no use in scissoring
5904
5905                         // reverse the cullface settings for this render
5906                         r_refdef.view.cullface_front = GL_FRONT;
5907                         r_refdef.view.cullface_back = GL_BACK;
5908                         // also reverse the view matrix
5909                         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
5910                         R_RenderView_UpdateViewVectors();
5911                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5912                         {
5913                                 r_refdef.view.usecustompvs = true;
5914                                 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);
5915                         }
5916                         
5917                         // camera needs no clipplane
5918                         r_refdef.view.useclipplane = false;
5919
5920                         PlaneClassify(&r_refdef.view.clipplane);
5921
5922                         r_fb.water.hideplayer = false;
5923
5924                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5925                         R_ClearScreen(r_refdef.fogenabled);
5926                         R_View_Update();
5927                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5928
5929                         if (!p->fbo_camera)
5930                                 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);
5931                         r_fb.water.hideplayer = false;
5932                 }
5933
5934         }
5935         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5936         r_fb.water.renderingscene = false;
5937         r_refdef.view = originalview;
5938         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5939         if (!r_fb.water.depthtexture)
5940                 R_ClearScreen(r_refdef.fogenabled);
5941         R_View_Update();
5942         goto finish;
5943 error:
5944         r_refdef.view = originalview;
5945         r_fb.water.renderingscene = false;
5946         Cvar_SetValueQuick(&r_water, 0);
5947         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5948 finish:
5949         // lowquality hack, restore cvars
5950         if (qualityreduction > 0)
5951         {
5952                 if (qualityreduction >= 1)
5953                 {
5954                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5955                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5956                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5957                 }
5958                 if (qualityreduction >= 2)
5959                 {
5960                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5961                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5962                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5963                 }
5964         }
5965 }
5966
5967 static void R_Bloom_StartFrame(void)
5968 {
5969         int i;
5970         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5971         int viewwidth, viewheight;
5972         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
5973         textype_t textype = TEXTYPE_COLORBUFFER;
5974
5975         switch (vid.renderpath)
5976         {
5977         case RENDERPATH_GL20:
5978                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
5979                 if (vid.support.ext_framebuffer_object)
5980                 {
5981                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5982                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5983                 }
5984                 break;
5985         case RENDERPATH_GL11:
5986         case RENDERPATH_GL13:
5987         case RENDERPATH_GLES1:
5988         case RENDERPATH_GLES2:
5989         case RENDERPATH_D3D9:
5990         case RENDERPATH_D3D10:
5991         case RENDERPATH_D3D11:
5992                 r_fb.usedepthtextures = false;
5993                 break;
5994         case RENDERPATH_SOFT:
5995                 r_fb.usedepthtextures = true;
5996                 break;
5997         }
5998
5999         if (r_viewscale_fpsscaling.integer)
6000         {
6001                 double actualframetime;
6002                 double targetframetime;
6003                 double adjust;
6004                 actualframetime = r_refdef.lastdrawscreentime;
6005                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6006                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6007                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6008                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6009                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6010                 viewscalefpsadjusted += adjust;
6011                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6012         }
6013         else
6014                 viewscalefpsadjusted = 1.0f;
6015
6016         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6017
6018         switch(vid.renderpath)
6019         {
6020         case RENDERPATH_GL20:
6021         case RENDERPATH_D3D9:
6022         case RENDERPATH_D3D10:
6023         case RENDERPATH_D3D11:
6024         case RENDERPATH_SOFT:
6025         case RENDERPATH_GLES2:
6026                 break;
6027         case RENDERPATH_GL11:
6028         case RENDERPATH_GL13:
6029         case RENDERPATH_GLES1:
6030                 return;
6031         }
6032
6033         // set bloomwidth and bloomheight to the bloom resolution that will be
6034         // used (often less than the screen resolution for faster rendering)
6035         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6036         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6037         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6038         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6039         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6040
6041         // calculate desired texture sizes
6042         if (vid.support.arb_texture_non_power_of_two)
6043         {
6044                 screentexturewidth = vid.width;
6045                 screentextureheight = vid.height;
6046                 bloomtexturewidth = r_fb.bloomwidth;
6047                 bloomtextureheight = r_fb.bloomheight;
6048         }
6049         else
6050         {
6051                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6052                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6053                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6054                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6055         }
6056
6057         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))
6058         {
6059                 Cvar_SetValueQuick(&r_bloom, 0);
6060                 Cvar_SetValueQuick(&r_motionblur, 0);
6061                 Cvar_SetValueQuick(&r_damageblur, 0);
6062         }
6063
6064         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6065          && !r_bloom.integer
6066          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6067          && !useviewfbo
6068          && r_viewscale.value == 1.0f
6069          && !r_viewscale_fpsscaling.integer)
6070                 screentexturewidth = screentextureheight = 0;
6071         if (!r_bloom.integer)
6072                 bloomtexturewidth = bloomtextureheight = 0;
6073
6074         // allocate textures as needed
6075         if (r_fb.screentexturewidth != screentexturewidth
6076          || r_fb.screentextureheight != screentextureheight
6077          || r_fb.bloomtexturewidth != bloomtexturewidth
6078          || r_fb.bloomtextureheight != bloomtextureheight
6079          || r_fb.textype != textype
6080          || useviewfbo != (r_fb.fbo != 0))
6081         {
6082                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6083                 {
6084                         if (r_fb.bloomtexture[i])
6085                                 R_FreeTexture(r_fb.bloomtexture[i]);
6086                         r_fb.bloomtexture[i] = NULL;
6087
6088                         if (r_fb.bloomfbo[i])
6089                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6090                         r_fb.bloomfbo[i] = 0;
6091                 }
6092
6093                 if (r_fb.fbo)
6094                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6095                 r_fb.fbo = 0;
6096
6097                 if (r_fb.colortexture)
6098                         R_FreeTexture(r_fb.colortexture);
6099                 r_fb.colortexture = NULL;
6100
6101                 if (r_fb.depthtexture)
6102                         R_FreeTexture(r_fb.depthtexture);
6103                 r_fb.depthtexture = NULL;
6104
6105                 if (r_fb.ghosttexture)
6106                         R_FreeTexture(r_fb.ghosttexture);
6107                 r_fb.ghosttexture = NULL;
6108
6109                 r_fb.screentexturewidth = screentexturewidth;
6110                 r_fb.screentextureheight = screentextureheight;
6111                 r_fb.bloomtexturewidth = bloomtexturewidth;
6112                 r_fb.bloomtextureheight = bloomtextureheight;
6113                 r_fb.textype = textype;
6114
6115                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6116                 {
6117                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6118                                 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);
6119                         r_fb.ghosttexture_valid = false;
6120                         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);
6121                         if (useviewfbo)
6122                         {
6123                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6124                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6125                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6126                         }
6127                 }
6128
6129                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6130                 {
6131                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6132                         {
6133                                 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);
6134                                 if (useviewfbo)
6135                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6136                         }
6137                 }
6138         }
6139
6140         // bloom texture is a different resolution
6141         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6142         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6143         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6144         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6145         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6146
6147         // set up a texcoord array for the full resolution screen image
6148         // (we have to keep this around to copy back during final render)
6149         r_fb.screentexcoord2f[0] = 0;
6150         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6151         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6152         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6153         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6154         r_fb.screentexcoord2f[5] = 0;
6155         r_fb.screentexcoord2f[6] = 0;
6156         r_fb.screentexcoord2f[7] = 0;
6157
6158         // set up a texcoord array for the reduced resolution bloom image
6159         // (which will be additive blended over the screen image)
6160         r_fb.bloomtexcoord2f[0] = 0;
6161         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6162         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6163         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6164         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6165         r_fb.bloomtexcoord2f[5] = 0;
6166         r_fb.bloomtexcoord2f[6] = 0;
6167         r_fb.bloomtexcoord2f[7] = 0;
6168
6169         switch(vid.renderpath)
6170         {
6171         case RENDERPATH_GL11:
6172         case RENDERPATH_GL13:
6173         case RENDERPATH_GL20:
6174         case RENDERPATH_SOFT:
6175         case RENDERPATH_GLES1:
6176         case RENDERPATH_GLES2:
6177                 break;
6178         case RENDERPATH_D3D9:
6179         case RENDERPATH_D3D10:
6180         case RENDERPATH_D3D11:
6181                 {
6182                         int i;
6183                         for (i = 0;i < 4;i++)
6184                         {
6185                                 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6186                                 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6187                                 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6188                                 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6189                         }
6190                 }
6191                 break;
6192         }
6193
6194         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, r_refdef.view.x, (r_fb.bloomfbo[0] ? r_fb.bloomtextureheight : vid.height) - r_fb.bloomheight - r_refdef.view.y, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6195
6196         if (r_fb.fbo)
6197                 r_refdef.view.clear = true;
6198 }
6199
6200 static void R_Bloom_MakeTexture(void)
6201 {
6202         int x, range, dir;
6203         float xoffset, yoffset, r, brighten;
6204         rtexture_t *intex;
6205         float colorscale = r_bloom_colorscale.value;
6206
6207         r_refdef.stats.bloom++;
6208
6209         if (!r_fb.fbo)
6210         {
6211                 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);
6212                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6213         }
6214
6215         // scale down screen texture to the bloom texture size
6216         CHECKGLERROR
6217         r_fb.bloomindex = 0;
6218         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6219         R_SetViewport(&r_fb.bloomviewport);
6220         GL_BlendFunc(GL_ONE, GL_ZERO);
6221         GL_Color(colorscale, colorscale, colorscale, 1);
6222         // 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...
6223         switch(vid.renderpath)
6224         {
6225         case RENDERPATH_GL11:
6226         case RENDERPATH_GL13:
6227         case RENDERPATH_GL20:
6228         case RENDERPATH_GLES1:
6229         case RENDERPATH_GLES2:
6230         case RENDERPATH_SOFT:
6231                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6232                 break;
6233         case RENDERPATH_D3D9:
6234         case RENDERPATH_D3D10:
6235         case RENDERPATH_D3D11:
6236                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6237                 break;
6238         }
6239         // TODO: do boxfilter scale-down in shader?
6240         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6241         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6242         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6243
6244         // we now have a properly scaled bloom image
6245         if (!r_fb.bloomfbo[r_fb.bloomindex])
6246         {
6247                 // copy it into the bloom texture
6248                 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);
6249                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6250         }
6251
6252         // multiply bloom image by itself as many times as desired
6253         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6254         {
6255                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6256                 r_fb.bloomindex ^= 1;
6257                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6258                 x *= 2;
6259                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6260                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6261                 {
6262                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6263                         GL_Color(r,r,r,1); // apply fix factor
6264                 }
6265                 else
6266                 {
6267                         if(x <= 2)
6268                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6269                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6270                         GL_Color(1,1,1,1); // no fix factor supported here
6271                 }
6272                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6273                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6274                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6275                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6276
6277                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6278                 {
6279                         // copy the darkened image to a texture
6280                         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);
6281                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6282                 }
6283         }
6284
6285         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6286         brighten = r_bloom_brighten.value;
6287         brighten = sqrt(brighten);
6288         if(range >= 1)
6289                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6290
6291         for (dir = 0;dir < 2;dir++)
6292         {
6293                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6294                 r_fb.bloomindex ^= 1;
6295                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6296                 // blend on at multiple vertical offsets to achieve a vertical blur
6297                 // TODO: do offset blends using GLSL
6298                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6299                 GL_BlendFunc(GL_ONE, GL_ZERO);
6300                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6301                 for (x = -range;x <= range;x++)
6302                 {
6303                         if (!dir){xoffset = 0;yoffset = x;}
6304                         else {xoffset = x;yoffset = 0;}
6305                         xoffset /= (float)r_fb.bloomtexturewidth;
6306                         yoffset /= (float)r_fb.bloomtextureheight;
6307                         // compute a texcoord array with the specified x and y offset
6308                         r_fb.offsettexcoord2f[0] = xoffset+0;
6309                         r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6310                         r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6311                         r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6312                         r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6313                         r_fb.offsettexcoord2f[5] = yoffset+0;
6314                         r_fb.offsettexcoord2f[6] = xoffset+0;
6315                         r_fb.offsettexcoord2f[7] = yoffset+0;
6316                         // this r value looks like a 'dot' particle, fading sharply to
6317                         // black at the edges
6318                         // (probably not realistic but looks good enough)
6319                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6320                         //r = brighten/(range*2+1);
6321                         r = brighten / (range * 2 + 1);
6322                         if(range >= 1)
6323                                 r *= (1 - x*x/(float)(range*range));
6324                         GL_Color(r, r, r, 1);
6325                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6326                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6327                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6328                         GL_BlendFunc(GL_ONE, GL_ONE);
6329                 }
6330
6331                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6332                 {
6333                         // copy the vertically or horizontally blurred bloom view to a texture
6334                         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);
6335                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6336                 }
6337         }
6338 }
6339
6340 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6341 {
6342         unsigned int permutation;
6343         float uservecs[4][4];
6344
6345         switch (vid.renderpath)
6346         {
6347         case RENDERPATH_GL20:
6348         case RENDERPATH_D3D9:
6349         case RENDERPATH_D3D10:
6350         case RENDERPATH_D3D11:
6351         case RENDERPATH_SOFT:
6352         case RENDERPATH_GLES2:
6353                 permutation =
6354                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6355                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6356                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6357                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6358                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6359
6360                 if (r_fb.colortexture)
6361                 {
6362                         if (!r_fb.fbo)
6363                         {
6364                                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6365                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6366                         }
6367
6368                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6369                         {
6370                                 // declare variables
6371                                 float blur_factor, blur_mouseaccel, blur_velocity;
6372                                 static float blur_average; 
6373                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6374
6375                                 // set a goal for the factoring
6376                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6377                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6378                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6379                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6380                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6381                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6382
6383                                 // from the goal, pick an averaged value between goal and last value
6384                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6385                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6386
6387                                 // enforce minimum amount of blur 
6388                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6389
6390                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6391
6392                                 // calculate values into a standard alpha
6393                                 cl.motionbluralpha = 1 - exp(-
6394                                                 (
6395                                                  (r_motionblur.value * blur_factor / 80)
6396                                                  +
6397                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6398                                                 )
6399                                                 /
6400                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6401                                           );
6402
6403                                 // randomization for the blur value to combat persistent ghosting
6404                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6405                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6406
6407                                 // apply the blur
6408                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6409                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6410                                 {
6411                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6412                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6413                                         switch(vid.renderpath)
6414                                         {
6415                                         case RENDERPATH_GL11:
6416                                         case RENDERPATH_GL13:
6417                                         case RENDERPATH_GL20:
6418                                         case RENDERPATH_GLES1:
6419                                         case RENDERPATH_GLES2:
6420                                         case RENDERPATH_SOFT:
6421                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6422                                                 break;
6423                                         case RENDERPATH_D3D9:
6424                                         case RENDERPATH_D3D10:
6425                                         case RENDERPATH_D3D11:
6426                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6427                                                 break;
6428                                         }
6429                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6430                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6431                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6432                                 }
6433
6434                                 // updates old view angles for next pass
6435                                 VectorCopy(cl.viewangles, blur_oldangles);
6436
6437                                 // copy view into the ghost texture
6438                                 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);
6439                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6440                                 r_fb.ghosttexture_valid = true;
6441                         }
6442                 }
6443                 else
6444                 {
6445                         // no r_fb.colortexture means we're rendering to the real fb
6446                         // we may still have to do view tint...
6447                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6448                         {
6449                                 // apply a color tint to the whole view
6450                                 R_ResetViewRendering2D(0, NULL, NULL);
6451                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6452                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6453                                 R_SetupShader_Generic_NoTexture(false, true);
6454                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6455                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6456                         }
6457                         break; // no screen processing, no bloom, skip it
6458                 }
6459
6460                 if (r_fb.bloomtexture[0])
6461                 {
6462                         // make the bloom texture
6463                         R_Bloom_MakeTexture();
6464                 }
6465
6466 #if _MSC_VER >= 1400
6467 #define sscanf sscanf_s
6468 #endif
6469                 memset(uservecs, 0, sizeof(uservecs));
6470                 if (r_glsl_postprocess_uservec1_enable.integer)
6471                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6472                 if (r_glsl_postprocess_uservec2_enable.integer)
6473                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6474                 if (r_glsl_postprocess_uservec3_enable.integer)
6475                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6476                 if (r_glsl_postprocess_uservec4_enable.integer)
6477                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6478
6479                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6480                 GL_Color(1, 1, 1, 1);
6481                 GL_BlendFunc(GL_ONE, GL_ZERO);
6482
6483                 switch(vid.renderpath)
6484                 {
6485                 case RENDERPATH_GL20:
6486                 case RENDERPATH_GLES2:
6487                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6488                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6489                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6490                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6491                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6492                         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]);
6493                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6494                         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]);
6495                         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]);
6496                         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]);
6497                         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]);
6498                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6499                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6500                         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);
6501                         break;
6502                 case RENDERPATH_D3D9:
6503 #ifdef SUPPORTD3D
6504                         // 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...
6505                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6506                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6507                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6508                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6509                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6510                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6511                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6512                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6513                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6514                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6515                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6516                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6517                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6518                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6519 #endif
6520                         break;
6521                 case RENDERPATH_D3D10:
6522                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6523                         break;
6524                 case RENDERPATH_D3D11:
6525                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6526                         break;
6527                 case RENDERPATH_SOFT:
6528                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6529                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6530                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6531                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6532                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6533                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6534                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6535                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6536                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6537                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6538                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6539                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6540                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6541                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6542                         break;
6543                 default:
6544                         break;
6545                 }
6546                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6547                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6548                 break;
6549         case RENDERPATH_GL11:
6550         case RENDERPATH_GL13:
6551         case RENDERPATH_GLES1:
6552                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6553                 {
6554                         // apply a color tint to the whole view
6555                         R_ResetViewRendering2D(0, NULL, NULL);
6556                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6557                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6558                         R_SetupShader_Generic_NoTexture(false, true);
6559                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6560                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6561                 }
6562                 break;
6563         }
6564 }
6565
6566 matrix4x4_t r_waterscrollmatrix;
6567
6568 void R_UpdateFog(void)
6569 {
6570         // Nehahra fog
6571         if (gamemode == GAME_NEHAHRA)
6572         {
6573                 if (gl_fogenable.integer)
6574                 {
6575                         r_refdef.oldgl_fogenable = true;
6576                         r_refdef.fog_density = gl_fogdensity.value;
6577                         r_refdef.fog_red = gl_fogred.value;
6578                         r_refdef.fog_green = gl_foggreen.value;
6579                         r_refdef.fog_blue = gl_fogblue.value;
6580                         r_refdef.fog_alpha = 1;
6581                         r_refdef.fog_start = 0;
6582                         r_refdef.fog_end = gl_skyclip.value;
6583                         r_refdef.fog_height = 1<<30;
6584                         r_refdef.fog_fadedepth = 128;
6585                 }
6586                 else if (r_refdef.oldgl_fogenable)
6587                 {
6588                         r_refdef.oldgl_fogenable = false;
6589                         r_refdef.fog_density = 0;
6590                         r_refdef.fog_red = 0;
6591                         r_refdef.fog_green = 0;
6592                         r_refdef.fog_blue = 0;
6593                         r_refdef.fog_alpha = 0;
6594                         r_refdef.fog_start = 0;
6595                         r_refdef.fog_end = 0;
6596                         r_refdef.fog_height = 1<<30;
6597                         r_refdef.fog_fadedepth = 128;
6598                 }
6599         }
6600
6601         // fog parms
6602         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6603         r_refdef.fog_start = max(0, r_refdef.fog_start);
6604         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6605
6606         if (r_refdef.fog_density && r_drawfog.integer)
6607         {
6608                 r_refdef.fogenabled = true;
6609                 // this is the point where the fog reaches 0.9986 alpha, which we
6610                 // consider a good enough cutoff point for the texture
6611                 // (0.9986 * 256 == 255.6)
6612                 if (r_fog_exp2.integer)
6613                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6614                 else
6615                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6616                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6617                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6618                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6619                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6620                         R_BuildFogHeightTexture();
6621                 // fog color was already set
6622                 // update the fog texture
6623                 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)
6624                         R_BuildFogTexture();
6625                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6626                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6627         }
6628         else
6629                 r_refdef.fogenabled = false;
6630
6631         // fog color
6632         if (r_refdef.fog_density)
6633         {
6634                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6635                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6636                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6637
6638                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6639                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6640                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6641                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6642
6643                 {
6644                         vec3_t fogvec;
6645                         VectorCopy(r_refdef.fogcolor, fogvec);
6646                         //   color.rgb *= ContrastBoost * SceneBrightness;
6647                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6648                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6649                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6650                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6651                 }
6652         }
6653 }
6654
6655 void R_UpdateVariables(void)
6656 {
6657         R_Textures_Frame();
6658
6659         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6660
6661         r_refdef.farclip = r_farclip_base.value;
6662         if (r_refdef.scene.worldmodel)
6663                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6664         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6665
6666         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6667                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6668         r_refdef.polygonfactor = 0;
6669         r_refdef.polygonoffset = 0;
6670         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6671         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6672
6673         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6674         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6675         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6676         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6677         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6678         if (FAKELIGHT_ENABLED)
6679         {
6680                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6681         }
6682         else if (r_refdef.scene.worldmodel)
6683         {
6684                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6685         }
6686         if (r_showsurfaces.integer)
6687         {
6688                 r_refdef.scene.rtworld = false;
6689                 r_refdef.scene.rtworldshadows = false;
6690                 r_refdef.scene.rtdlight = false;
6691                 r_refdef.scene.rtdlightshadows = false;
6692                 r_refdef.lightmapintensity = 0;
6693         }
6694
6695         switch(vid.renderpath)
6696         {
6697         case RENDERPATH_GL20:
6698         case RENDERPATH_D3D9:
6699         case RENDERPATH_D3D10:
6700         case RENDERPATH_D3D11:
6701         case RENDERPATH_SOFT:
6702         case RENDERPATH_GLES2:
6703                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6704                 {
6705                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6706                         {
6707                                 // build GLSL gamma texture
6708 #define RAMPWIDTH 256
6709                                 unsigned short ramp[RAMPWIDTH * 3];
6710                                 unsigned char rampbgr[RAMPWIDTH][4];
6711                                 int i;
6712
6713                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6714
6715                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6716                                 for(i = 0; i < RAMPWIDTH; ++i)
6717                                 {
6718                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6719                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6720                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6721                                         rampbgr[i][3] = 0;
6722                                 }
6723                                 if (r_texture_gammaramps)
6724                                 {
6725                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6726                                 }
6727                                 else
6728                                 {
6729                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6730                                 }
6731                         }
6732                 }
6733                 else
6734                 {
6735                         // remove GLSL gamma texture
6736                 }
6737                 break;
6738         case RENDERPATH_GL11:
6739         case RENDERPATH_GL13:
6740         case RENDERPATH_GLES1:
6741                 break;
6742         }
6743 }
6744
6745 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6746 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6747 /*
6748 ================
6749 R_SelectScene
6750 ================
6751 */
6752 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6753         if( scenetype != r_currentscenetype ) {
6754                 // store the old scenetype
6755                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6756                 r_currentscenetype = scenetype;
6757                 // move in the new scene
6758                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6759         }
6760 }
6761
6762 /*
6763 ================
6764 R_GetScenePointer
6765 ================
6766 */
6767 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6768 {
6769         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6770         if( scenetype == r_currentscenetype ) {
6771                 return &r_refdef.scene;
6772         } else {
6773                 return &r_scenes_store[ scenetype ];
6774         }
6775 }
6776
6777 static int R_SortEntities_Compare(const void *ap, const void *bp)
6778 {
6779         const entity_render_t *a = *(const entity_render_t **)ap;
6780         const entity_render_t *b = *(const entity_render_t **)bp;
6781
6782         // 1. compare model
6783         if(a->model < b->model)
6784                 return -1;
6785         if(a->model > b->model)
6786                 return +1;
6787
6788         // 2. compare skin
6789         // TODO possibly calculate the REAL skinnum here first using
6790         // skinscenes?
6791         if(a->skinnum < b->skinnum)
6792                 return -1;
6793         if(a->skinnum > b->skinnum)
6794                 return +1;
6795
6796         // everything we compared is equal
6797         return 0;
6798 }
6799 static void R_SortEntities(void)
6800 {
6801         // below or equal 2 ents, sorting never gains anything
6802         if(r_refdef.scene.numentities <= 2)
6803                 return;
6804         // sort
6805         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6806 }
6807
6808 /*
6809 ================
6810 R_RenderView
6811 ================
6812 */
6813 int dpsoftrast_test;
6814 extern cvar_t r_shadow_bouncegrid;
6815 void R_RenderView(void)
6816 {
6817         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6818         int fbo;
6819         rtexture_t *depthtexture;
6820         rtexture_t *colortexture;
6821
6822         dpsoftrast_test = r_test.integer;
6823
6824         if (r_timereport_active)
6825                 R_TimeReport("start");
6826         r_textureframe++; // used only by R_GetCurrentTexture
6827         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6828
6829         if(R_CompileShader_CheckStaticParms())
6830                 R_GLSL_Restart_f();
6831
6832         if (!r_drawentities.integer)
6833                 r_refdef.scene.numentities = 0;
6834         else if (r_sortentities.integer)
6835                 R_SortEntities();
6836
6837         R_AnimCache_ClearCache();
6838         R_FrameData_NewFrame();
6839
6840         /* adjust for stereo display */
6841         if(R_Stereo_Active())
6842         {
6843                 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);
6844                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6845         }
6846
6847         if (r_refdef.view.isoverlay)
6848         {
6849                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6850                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6851                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6852                 R_TimeReport("depthclear");
6853
6854                 r_refdef.view.showdebug = false;
6855
6856                 r_fb.water.enabled = false;
6857                 r_fb.water.numwaterplanes = 0;
6858
6859                 R_RenderScene(0, NULL, NULL);
6860
6861                 r_refdef.view.matrix = originalmatrix;
6862
6863                 CHECKGLERROR
6864                 return;
6865         }
6866
6867         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6868         {
6869                 r_refdef.view.matrix = originalmatrix;
6870                 return;
6871         }
6872
6873         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6874
6875         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6876                 // in sRGB fallback, behave similar to true sRGB: convert this
6877                 // value from linear to sRGB
6878                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6879
6880         R_RenderView_UpdateViewVectors();
6881
6882         R_Shadow_UpdateWorldLightSelection();
6883
6884         R_Bloom_StartFrame();
6885         R_Water_StartFrame();
6886
6887         // now we probably have an fbo to render into
6888         fbo = r_fb.fbo;
6889         depthtexture = r_fb.depthtexture;
6890         colortexture = r_fb.colortexture;
6891
6892         CHECKGLERROR
6893         if (r_timereport_active)
6894                 R_TimeReport("viewsetup");
6895
6896         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6897
6898         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6899         {
6900                 R_ClearScreen(r_refdef.fogenabled);
6901                 if (r_timereport_active)
6902                         R_TimeReport("viewclear");
6903         }
6904         r_refdef.view.clear = true;
6905
6906         r_refdef.view.showdebug = true;
6907
6908         R_View_Update();
6909         if (r_timereport_active)
6910                 R_TimeReport("visibility");
6911
6912         R_Shadow_UpdateBounceGridTexture();
6913         if (r_timereport_active && r_shadow_bouncegrid.integer)
6914                 R_TimeReport("bouncegrid");
6915
6916         r_fb.water.numwaterplanes = 0;
6917         if (r_fb.water.enabled)
6918                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6919
6920         R_RenderScene(fbo, depthtexture, colortexture);
6921         r_fb.water.numwaterplanes = 0;
6922
6923         R_BlendView(fbo, depthtexture, colortexture);
6924         if (r_timereport_active)
6925                 R_TimeReport("blendview");
6926
6927         GL_Scissor(0, 0, vid.width, vid.height);
6928         GL_ScissorTest(false);
6929
6930         r_refdef.view.matrix = originalmatrix;
6931
6932         CHECKGLERROR
6933 }
6934
6935 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6936 {
6937         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6938         {
6939                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6940                 if (r_timereport_active)
6941                         R_TimeReport("waterworld");
6942         }
6943
6944         // don't let sound skip if going slow
6945         if (r_refdef.scene.extraupdate)
6946                 S_ExtraUpdate ();
6947
6948         R_DrawModelsAddWaterPlanes();
6949         if (r_timereport_active)
6950                 R_TimeReport("watermodels");
6951
6952         if (r_fb.water.numwaterplanes)
6953         {
6954                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6955                 if (r_timereport_active)
6956                         R_TimeReport("waterscenes");
6957         }
6958 }
6959
6960 extern cvar_t cl_locs_show;
6961 static void R_DrawLocs(void);
6962 static void R_DrawEntityBBoxes(void);
6963 static void R_DrawModelDecals(void);
6964 extern cvar_t cl_decals_newsystem;
6965 extern qboolean r_shadow_usingdeferredprepass;
6966 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6967 {
6968         qboolean shadowmapping = false;
6969
6970         if (r_timereport_active)
6971                 R_TimeReport("beginscene");
6972
6973         r_refdef.stats.renders++;
6974
6975         R_UpdateFog();
6976
6977         // don't let sound skip if going slow
6978         if (r_refdef.scene.extraupdate)
6979                 S_ExtraUpdate ();
6980
6981         R_MeshQueue_BeginScene();
6982
6983         R_SkyStartFrame();
6984
6985         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);
6986
6987         if (r_timereport_active)
6988                 R_TimeReport("skystartframe");
6989
6990         if (cl.csqc_vidvars.drawworld)
6991         {
6992                 // don't let sound skip if going slow
6993                 if (r_refdef.scene.extraupdate)
6994                         S_ExtraUpdate ();
6995
6996                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6997                 {
6998                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6999                         if (r_timereport_active)
7000                                 R_TimeReport("worldsky");
7001                 }
7002
7003                 if (R_DrawBrushModelsSky() && r_timereport_active)
7004                         R_TimeReport("bmodelsky");
7005
7006                 if (skyrendermasked && skyrenderlater)
7007                 {
7008                         // we have to force off the water clipping plane while rendering sky
7009                         R_SetupView(false, fbo, depthtexture, colortexture);
7010                         R_Sky();
7011                         R_SetupView(true, fbo, depthtexture, colortexture);
7012                         if (r_timereport_active)
7013                                 R_TimeReport("sky");
7014                 }
7015         }
7016
7017         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7018         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7019                 R_Shadow_PrepareModelShadows();
7020         if (r_timereport_active)
7021                 R_TimeReport("preparelights");
7022
7023         if (R_Shadow_ShadowMappingEnabled())
7024                 shadowmapping = true;
7025
7026         if (r_shadow_usingdeferredprepass)
7027                 R_Shadow_DrawPrepass();
7028
7029         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7030         {
7031                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7032                 if (r_timereport_active)
7033                         R_TimeReport("worlddepth");
7034         }
7035         if (r_depthfirst.integer >= 2)
7036         {
7037                 R_DrawModelsDepth();
7038                 if (r_timereport_active)
7039                         R_TimeReport("modeldepth");
7040         }
7041
7042         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7043         {
7044                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7045                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7046                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7047                 // don't let sound skip if going slow
7048                 if (r_refdef.scene.extraupdate)
7049                         S_ExtraUpdate ();
7050         }
7051
7052         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7053         {
7054                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7055                 if (r_timereport_active)
7056                         R_TimeReport("world");
7057         }
7058
7059         // don't let sound skip if going slow
7060         if (r_refdef.scene.extraupdate)
7061                 S_ExtraUpdate ();
7062
7063         R_DrawModels();
7064         if (r_timereport_active)
7065                 R_TimeReport("models");
7066
7067         // don't let sound skip if going slow
7068         if (r_refdef.scene.extraupdate)
7069                 S_ExtraUpdate ();
7070
7071         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7072         {
7073                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7074                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7075                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7076                 // don't let sound skip if going slow
7077                 if (r_refdef.scene.extraupdate)
7078                         S_ExtraUpdate ();
7079         }
7080
7081         if (!r_shadow_usingdeferredprepass)
7082         {
7083                 R_Shadow_DrawLights();
7084                 if (r_timereport_active)
7085                         R_TimeReport("rtlights");
7086         }
7087
7088         // don't let sound skip if going slow
7089         if (r_refdef.scene.extraupdate)
7090                 S_ExtraUpdate ();
7091
7092         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7093         {
7094                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7095                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7096                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7097                 // don't let sound skip if going slow
7098                 if (r_refdef.scene.extraupdate)
7099                         S_ExtraUpdate ();
7100         }
7101
7102         if (cl.csqc_vidvars.drawworld)
7103         {
7104                 if (cl_decals_newsystem.integer)
7105                 {
7106                         R_DrawModelDecals();
7107                         if (r_timereport_active)
7108                                 R_TimeReport("modeldecals");
7109                 }
7110                 else
7111                 {
7112                         R_DrawDecals();
7113                         if (r_timereport_active)
7114                                 R_TimeReport("decals");
7115                 }
7116
7117                 R_DrawParticles();
7118                 if (r_timereport_active)
7119                         R_TimeReport("particles");
7120
7121                 R_DrawExplosions();
7122                 if (r_timereport_active)
7123                         R_TimeReport("explosions");
7124
7125                 R_DrawLightningBeams();
7126                 if (r_timereport_active)
7127                         R_TimeReport("lightning");
7128         }
7129
7130         if (cl.csqc_loaded)
7131                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7132
7133         if (r_refdef.view.showdebug)
7134         {
7135                 if (cl_locs_show.integer)
7136                 {
7137                         R_DrawLocs();
7138                         if (r_timereport_active)
7139                                 R_TimeReport("showlocs");
7140                 }
7141
7142                 if (r_drawportals.integer)
7143                 {
7144                         R_DrawPortals();
7145                         if (r_timereport_active)
7146                                 R_TimeReport("portals");
7147                 }
7148
7149                 if (r_showbboxes.value > 0)
7150                 {
7151                         R_DrawEntityBBoxes();
7152                         if (r_timereport_active)
7153                                 R_TimeReport("bboxes");
7154                 }
7155         }
7156
7157         if (r_transparent.integer)
7158         {
7159                 R_MeshQueue_RenderTransparent();
7160                 if (r_timereport_active)
7161                         R_TimeReport("drawtrans");
7162         }
7163
7164         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))
7165         {
7166                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7167                 if (r_timereport_active)
7168                         R_TimeReport("worlddebug");
7169                 R_DrawModelsDebug();
7170                 if (r_timereport_active)
7171                         R_TimeReport("modeldebug");
7172         }
7173
7174         if (cl.csqc_vidvars.drawworld)
7175         {
7176                 R_Shadow_DrawCoronas();
7177                 if (r_timereport_active)
7178                         R_TimeReport("coronas");
7179         }
7180
7181 #if 0
7182         {
7183                 GL_DepthTest(false);
7184                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7185                 GL_Color(1, 1, 1, 1);
7186                 qglBegin(GL_POLYGON);
7187                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7188                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7189                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7190                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7191                 qglEnd();
7192                 qglBegin(GL_POLYGON);
7193                 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]);
7194                 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]);
7195                 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]);
7196                 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]);
7197                 qglEnd();
7198                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7199         }
7200 #endif
7201
7202         // don't let sound skip if going slow
7203         if (r_refdef.scene.extraupdate)
7204                 S_ExtraUpdate ();
7205 }
7206
7207 static const unsigned short bboxelements[36] =
7208 {
7209         5, 1, 3, 5, 3, 7,
7210         6, 2, 0, 6, 0, 4,
7211         7, 3, 2, 7, 2, 6,
7212         4, 0, 1, 4, 1, 5,
7213         4, 5, 7, 4, 7, 6,
7214         1, 0, 2, 1, 2, 3,
7215 };
7216
7217 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7218 {
7219         int i;
7220         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7221
7222         RSurf_ActiveWorldEntity();
7223
7224         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7225         GL_DepthMask(false);
7226         GL_DepthRange(0, 1);
7227         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7228 //      R_Mesh_ResetTextureState();
7229
7230         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7231         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7232         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7233         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7234         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7235         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7236         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7237         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7238         R_FillColors(color4f, 8, cr, cg, cb, ca);
7239         if (r_refdef.fogenabled)
7240         {
7241                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7242                 {
7243                         f1 = RSurf_FogVertex(v);
7244                         f2 = 1 - f1;
7245                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7246                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7247                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7248                 }
7249         }
7250         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7251         R_Mesh_ResetTextureState();
7252         R_SetupShader_Generic_NoTexture(false, false);
7253         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7254 }
7255
7256 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7257 {
7258         prvm_prog_t *prog = SVVM_prog;
7259         int i;
7260         float color[4];
7261         prvm_edict_t *edict;
7262
7263         // this function draws bounding boxes of server entities
7264         if (!sv.active)
7265                 return;
7266
7267         GL_CullFace(GL_NONE);
7268         R_SetupShader_Generic_NoTexture(false, false);
7269
7270         for (i = 0;i < numsurfaces;i++)
7271         {
7272                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7273                 switch ((int)PRVM_serveredictfloat(edict, solid))
7274                 {
7275                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7276                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7277                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7278                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7279                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7280                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7281                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7282                 }
7283                 color[3] *= r_showbboxes.value;
7284                 color[3] = bound(0, color[3], 1);
7285                 GL_DepthTest(!r_showdisabledepthtest.integer);
7286                 GL_CullFace(r_refdef.view.cullface_front);
7287                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7288         }
7289 }
7290
7291 static void R_DrawEntityBBoxes(void)
7292 {
7293         int i;
7294         prvm_edict_t *edict;
7295         vec3_t center;
7296         prvm_prog_t *prog = SVVM_prog;
7297
7298         // this function draws bounding boxes of server entities
7299         if (!sv.active)
7300                 return;
7301
7302         for (i = 0;i < prog->num_edicts;i++)
7303         {
7304                 edict = PRVM_EDICT_NUM(i);
7305                 if (edict->priv.server->free)
7306                         continue;
7307                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7308                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7309                         continue;
7310                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7311                         continue;
7312                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7313                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7314         }
7315 }
7316
7317 static const int nomodelelement3i[24] =
7318 {
7319         5, 2, 0,
7320         5, 1, 2,
7321         5, 0, 3,
7322         5, 3, 1,
7323         0, 2, 4,
7324         2, 1, 4,
7325         3, 0, 4,
7326         1, 3, 4
7327 };
7328
7329 static const unsigned short nomodelelement3s[24] =
7330 {
7331         5, 2, 0,
7332         5, 1, 2,
7333         5, 0, 3,
7334         5, 3, 1,
7335         0, 2, 4,
7336         2, 1, 4,
7337         3, 0, 4,
7338         1, 3, 4
7339 };
7340
7341 static const float nomodelvertex3f[6*3] =
7342 {
7343         -16,   0,   0,
7344          16,   0,   0,
7345           0, -16,   0,
7346           0,  16,   0,
7347           0,   0, -16,
7348           0,   0,  16
7349 };
7350
7351 static const float nomodelcolor4f[6*4] =
7352 {
7353         0.0f, 0.0f, 0.5f, 1.0f,
7354         0.0f, 0.0f, 0.5f, 1.0f,
7355         0.0f, 0.5f, 0.0f, 1.0f,
7356         0.0f, 0.5f, 0.0f, 1.0f,
7357         0.5f, 0.0f, 0.0f, 1.0f,
7358         0.5f, 0.0f, 0.0f, 1.0f
7359 };
7360
7361 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7362 {
7363         int i;
7364         float f1, f2, *c;
7365         float color4f[6*4];
7366
7367         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);
7368
7369         // this is only called once per entity so numsurfaces is always 1, and
7370         // surfacelist is always {0}, so this code does not handle batches
7371
7372         if (rsurface.ent_flags & RENDER_ADDITIVE)
7373         {
7374                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7375                 GL_DepthMask(false);
7376         }
7377         else if (rsurface.colormod[3] < 1)
7378         {
7379                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7380                 GL_DepthMask(false);
7381         }
7382         else
7383         {
7384                 GL_BlendFunc(GL_ONE, GL_ZERO);
7385                 GL_DepthMask(true);
7386         }
7387         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7388         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7389         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7390         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7391         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7392         for (i = 0, c = color4f;i < 6;i++, c += 4)
7393         {
7394                 c[0] *= rsurface.colormod[0];
7395                 c[1] *= rsurface.colormod[1];
7396                 c[2] *= rsurface.colormod[2];
7397                 c[3] *= rsurface.colormod[3];
7398         }
7399         if (r_refdef.fogenabled)
7400         {
7401                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7402                 {
7403                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7404                         f2 = 1 - f1;
7405                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7406                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7407                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7408                 }
7409         }
7410 //      R_Mesh_ResetTextureState();
7411         R_SetupShader_Generic_NoTexture(false, false);
7412         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7413         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7414 }
7415
7416 void R_DrawNoModel(entity_render_t *ent)
7417 {
7418         vec3_t org;
7419         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7420         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7421                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7422         else
7423                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7424 }
7425
7426 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7427 {
7428         vec3_t right1, right2, diff, normal;
7429
7430         VectorSubtract (org2, org1, normal);
7431
7432         // calculate 'right' vector for start
7433         VectorSubtract (r_refdef.view.origin, org1, diff);
7434         CrossProduct (normal, diff, right1);
7435         VectorNormalize (right1);
7436
7437         // calculate 'right' vector for end
7438         VectorSubtract (r_refdef.view.origin, org2, diff);
7439         CrossProduct (normal, diff, right2);
7440         VectorNormalize (right2);
7441
7442         vert[ 0] = org1[0] + width * right1[0];
7443         vert[ 1] = org1[1] + width * right1[1];
7444         vert[ 2] = org1[2] + width * right1[2];
7445         vert[ 3] = org1[0] - width * right1[0];
7446         vert[ 4] = org1[1] - width * right1[1];
7447         vert[ 5] = org1[2] - width * right1[2];
7448         vert[ 6] = org2[0] - width * right2[0];
7449         vert[ 7] = org2[1] - width * right2[1];
7450         vert[ 8] = org2[2] - width * right2[2];
7451         vert[ 9] = org2[0] + width * right2[0];
7452         vert[10] = org2[1] + width * right2[1];
7453         vert[11] = org2[2] + width * right2[2];
7454 }
7455
7456 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)
7457 {
7458         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7459         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7460         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7461         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7462         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7463         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7464         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7465         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7466         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7467         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7468         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7469         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7470 }
7471
7472 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7473 {
7474         int i;
7475         float *vertex3f;
7476         float v[3];
7477         VectorSet(v, x, y, z);
7478         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7479                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7480                         break;
7481         if (i == mesh->numvertices)
7482         {
7483                 if (mesh->numvertices < mesh->maxvertices)
7484                 {
7485                         VectorCopy(v, vertex3f);
7486                         mesh->numvertices++;
7487                 }
7488                 return mesh->numvertices;
7489         }
7490         else
7491                 return i;
7492 }
7493
7494 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7495 {
7496         int i;
7497         int *e, element[3];
7498         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7499         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7500         e = mesh->element3i + mesh->numtriangles * 3;
7501         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7502         {
7503                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7504                 if (mesh->numtriangles < mesh->maxtriangles)
7505                 {
7506                         *e++ = element[0];
7507                         *e++ = element[1];
7508                         *e++ = element[2];
7509                         mesh->numtriangles++;
7510                 }
7511                 element[1] = element[2];
7512         }
7513 }
7514
7515 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7516 {
7517         int i;
7518         int *e, element[3];
7519         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7520         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7521         e = mesh->element3i + mesh->numtriangles * 3;
7522         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7523         {
7524                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7525                 if (mesh->numtriangles < mesh->maxtriangles)
7526                 {
7527                         *e++ = element[0];
7528                         *e++ = element[1];
7529                         *e++ = element[2];
7530                         mesh->numtriangles++;
7531                 }
7532                 element[1] = element[2];
7533         }
7534 }
7535
7536 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7537 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7538 {
7539         int planenum, planenum2;
7540         int w;
7541         int tempnumpoints;
7542         mplane_t *plane, *plane2;
7543         double maxdist;
7544         double temppoints[2][256*3];
7545         // figure out how large a bounding box we need to properly compute this brush
7546         maxdist = 0;
7547         for (w = 0;w < numplanes;w++)
7548                 maxdist = max(maxdist, fabs(planes[w].dist));
7549         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7550         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7551         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7552         {
7553                 w = 0;
7554                 tempnumpoints = 4;
7555                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7556                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7557                 {
7558                         if (planenum2 == planenum)
7559                                 continue;
7560                         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);
7561                         w = !w;
7562                 }
7563                 if (tempnumpoints < 3)
7564                         continue;
7565                 // generate elements forming a triangle fan for this polygon
7566                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7567         }
7568 }
7569
7570 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)
7571 {
7572         texturelayer_t *layer;
7573         layer = t->currentlayers + t->currentnumlayers++;
7574         layer->type = type;
7575         layer->depthmask = depthmask;
7576         layer->blendfunc1 = blendfunc1;
7577         layer->blendfunc2 = blendfunc2;
7578         layer->texture = texture;
7579         layer->texmatrix = *matrix;
7580         layer->color[0] = r;
7581         layer->color[1] = g;
7582         layer->color[2] = b;
7583         layer->color[3] = a;
7584 }
7585
7586 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7587 {
7588         if(parms[0] == 0 && parms[1] == 0)
7589                 return false;
7590         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7591                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7592                         return false;
7593         return true;
7594 }
7595
7596 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7597 {
7598         double index, f;
7599         index = parms[2] + rsurface.shadertime * parms[3];
7600         index -= floor(index);
7601         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7602         {
7603         default:
7604         case Q3WAVEFUNC_NONE:
7605         case Q3WAVEFUNC_NOISE:
7606         case Q3WAVEFUNC_COUNT:
7607                 f = 0;
7608                 break;
7609         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7610         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7611         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7612         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7613         case Q3WAVEFUNC_TRIANGLE:
7614                 index *= 4;
7615                 f = index - floor(index);
7616                 if (index < 1)
7617                 {
7618                         // f = f;
7619                 }
7620                 else if (index < 2)
7621                         f = 1 - f;
7622                 else if (index < 3)
7623                         f = -f;
7624                 else
7625                         f = -(1 - f);
7626                 break;
7627         }
7628         f = parms[0] + parms[1] * f;
7629         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7630                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7631         return (float) f;
7632 }
7633
7634 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7635 {
7636         int w, h, idx;
7637         double f;
7638         double offsetd[2];
7639         float tcmat[12];
7640         matrix4x4_t matrix, temp;
7641         switch(tcmod->tcmod)
7642         {
7643                 case Q3TCMOD_COUNT:
7644                 case Q3TCMOD_NONE:
7645                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7646                                 matrix = r_waterscrollmatrix;
7647                         else
7648                                 matrix = identitymatrix;
7649                         break;
7650                 case Q3TCMOD_ENTITYTRANSLATE:
7651                         // this is used in Q3 to allow the gamecode to control texcoord
7652                         // scrolling on the entity, which is not supported in darkplaces yet.
7653                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7654                         break;
7655                 case Q3TCMOD_ROTATE:
7656                         f = tcmod->parms[0] * rsurface.shadertime;
7657                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7658                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7659                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7660                         break;
7661                 case Q3TCMOD_SCALE:
7662                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7663                         break;
7664                 case Q3TCMOD_SCROLL:
7665                         // extra care is needed because of precision breakdown with large values of time
7666                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7667                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7668                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7669                         break;
7670                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7671                         w = (int) tcmod->parms[0];
7672                         h = (int) tcmod->parms[1];
7673                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7674                         f = f - floor(f);
7675                         idx = (int) floor(f * w * h);
7676                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7677                         break;
7678                 case Q3TCMOD_STRETCH:
7679                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7680                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7681                         break;
7682                 case Q3TCMOD_TRANSFORM:
7683                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7684                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7685                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7686                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7687                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7688                         break;
7689                 case Q3TCMOD_TURBULENT:
7690                         // this is handled in the RSurf_PrepareVertices function
7691                         matrix = identitymatrix;
7692                         break;
7693         }
7694         temp = *texmatrix;
7695         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7696 }
7697
7698 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7699 {
7700         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7701         char name[MAX_QPATH];
7702         skinframe_t *skinframe;
7703         unsigned char pixels[296*194];
7704         strlcpy(cache->name, skinname, sizeof(cache->name));
7705         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7706         if (developer_loading.integer)
7707                 Con_Printf("loading %s\n", name);
7708         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7709         if (!skinframe || !skinframe->base)
7710         {
7711                 unsigned char *f;
7712                 fs_offset_t filesize;
7713                 skinframe = NULL;
7714                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7715                 if (f)
7716                 {
7717                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7718                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7719                         Mem_Free(f);
7720                 }
7721         }
7722         cache->skinframe = skinframe;
7723 }
7724
7725 texture_t *R_GetCurrentTexture(texture_t *t)
7726 {
7727         int i;
7728         const entity_render_t *ent = rsurface.entity;
7729         dp_model_t *model = ent->model;
7730         q3shaderinfo_layer_tcmod_t *tcmod;
7731
7732         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7733                 return t->currentframe;
7734         t->update_lastrenderframe = r_textureframe;
7735         t->update_lastrenderentity = (void *)ent;
7736
7737         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7738                 t->camera_entity = ent->entitynumber;
7739         else
7740                 t->camera_entity = 0;
7741
7742         // switch to an alternate material if this is a q1bsp animated material
7743         {
7744                 texture_t *texture = t;
7745                 int s = rsurface.ent_skinnum;
7746                 if ((unsigned int)s >= (unsigned int)model->numskins)
7747                         s = 0;
7748                 if (model->skinscenes)
7749                 {
7750                         if (model->skinscenes[s].framecount > 1)
7751                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7752                         else
7753                                 s = model->skinscenes[s].firstframe;
7754                 }
7755                 if (s > 0)
7756                         t = t + s * model->num_surfaces;
7757                 if (t->animated)
7758                 {
7759                         // use an alternate animation if the entity's frame is not 0,
7760                         // and only if the texture has an alternate animation
7761                         if (rsurface.ent_alttextures && t->anim_total[1])
7762                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7763                         else
7764                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7765                 }
7766                 texture->currentframe = t;
7767         }
7768
7769         // update currentskinframe to be a qw skin or animation frame
7770         if (rsurface.ent_qwskin >= 0)
7771         {
7772                 i = rsurface.ent_qwskin;
7773                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7774                 {
7775                         r_qwskincache_size = cl.maxclients;
7776                         if (r_qwskincache)
7777                                 Mem_Free(r_qwskincache);
7778                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7779                 }
7780                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7781                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7782                 t->currentskinframe = r_qwskincache[i].skinframe;
7783                 if (t->currentskinframe == NULL)
7784                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7785         }
7786         else if (t->numskinframes >= 2)
7787                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7788         if (t->backgroundnumskinframes >= 2)
7789                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7790
7791         t->currentmaterialflags = t->basematerialflags;
7792         t->currentalpha = rsurface.colormod[3];
7793         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7794                 t->currentalpha *= r_wateralpha.value;
7795         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7796                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7797         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7798                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7799         if (!(rsurface.ent_flags & RENDER_LIGHT))
7800                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7801         else if (FAKELIGHT_ENABLED)
7802         {
7803                 // no modellight if using fakelight for the map
7804         }
7805         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7806         {
7807                 // pick a model lighting mode
7808                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7809                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7810                 else
7811                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7812         }
7813         if (rsurface.ent_flags & RENDER_ADDITIVE)
7814                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7815         else if (t->currentalpha < 1)
7816                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7817         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7818         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7819                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7820         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7821                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7822         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7823                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7824         if (t->backgroundnumskinframes)
7825                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7826         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7827         {
7828                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7829                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7830         }
7831         else
7832                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7833         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7834         {
7835                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7836                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7837         }
7838         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7839                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7840
7841         // there is no tcmod
7842         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7843         {
7844                 t->currenttexmatrix = r_waterscrollmatrix;
7845                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7846         }
7847         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7848         {
7849                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7850                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7851         }
7852
7853         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7854                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7855         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7856                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7857
7858         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7859         if (t->currentskinframe->qpixels)
7860                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7861         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7862         if (!t->basetexture)
7863                 t->basetexture = r_texture_notexture;
7864         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7865         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7866         t->nmaptexture = t->currentskinframe->nmap;
7867         if (!t->nmaptexture)
7868                 t->nmaptexture = r_texture_blanknormalmap;
7869         t->glosstexture = r_texture_black;
7870         t->glowtexture = t->currentskinframe->glow;
7871         t->fogtexture = t->currentskinframe->fog;
7872         t->reflectmasktexture = t->currentskinframe->reflect;
7873         if (t->backgroundnumskinframes)
7874         {
7875                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7876                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7877                 t->backgroundglosstexture = r_texture_black;
7878                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7879                 if (!t->backgroundnmaptexture)
7880                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7881         }
7882         else
7883         {
7884                 t->backgroundbasetexture = r_texture_white;
7885                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7886                 t->backgroundglosstexture = r_texture_black;
7887                 t->backgroundglowtexture = NULL;
7888         }
7889         t->specularpower = r_shadow_glossexponent.value;
7890         // TODO: store reference values for these in the texture?
7891         t->specularscale = 0;
7892         if (r_shadow_gloss.integer > 0)
7893         {
7894                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7895                 {
7896                         if (r_shadow_glossintensity.value > 0)
7897                         {
7898                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7899                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7900                                 t->specularscale = r_shadow_glossintensity.value;
7901                         }
7902                 }
7903                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7904                 {
7905                         t->glosstexture = r_texture_white;
7906                         t->backgroundglosstexture = r_texture_white;
7907                         t->specularscale = r_shadow_gloss2intensity.value;
7908                         t->specularpower = r_shadow_gloss2exponent.value;
7909                 }
7910         }
7911         t->specularscale *= t->specularscalemod;
7912         t->specularpower *= t->specularpowermod;
7913         t->rtlightambient = 0;
7914
7915         // lightmaps mode looks bad with dlights using actual texturing, so turn
7916         // off the colormap and glossmap, but leave the normalmap on as it still
7917         // accurately represents the shading involved
7918         if (gl_lightmaps.integer)
7919         {
7920                 t->basetexture = r_texture_grey128;
7921                 t->pantstexture = r_texture_black;
7922                 t->shirttexture = r_texture_black;
7923                 t->nmaptexture = r_texture_blanknormalmap;
7924                 t->glosstexture = r_texture_black;
7925                 t->glowtexture = NULL;
7926                 t->fogtexture = NULL;
7927                 t->reflectmasktexture = NULL;
7928                 t->backgroundbasetexture = NULL;
7929                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7930                 t->backgroundglosstexture = r_texture_black;
7931                 t->backgroundglowtexture = NULL;
7932                 t->specularscale = 0;
7933                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7934         }
7935
7936         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7937         VectorClear(t->dlightcolor);
7938         t->currentnumlayers = 0;
7939         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7940         {
7941                 int blendfunc1, blendfunc2;
7942                 qboolean depthmask;
7943                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7944                 {
7945                         blendfunc1 = GL_SRC_ALPHA;
7946                         blendfunc2 = GL_ONE;
7947                 }
7948                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7949                 {
7950                         blendfunc1 = GL_SRC_ALPHA;
7951                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7952                 }
7953                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7954                 {
7955                         blendfunc1 = t->customblendfunc[0];
7956                         blendfunc2 = t->customblendfunc[1];
7957                 }
7958                 else
7959                 {
7960                         blendfunc1 = GL_ONE;
7961                         blendfunc2 = GL_ZERO;
7962                 }
7963                 // don't colormod evilblend textures
7964                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7965                         VectorSet(t->lightmapcolor, 1, 1, 1);
7966                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7967                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7968                 {
7969                         // fullbright is not affected by r_refdef.lightmapintensity
7970                         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]);
7971                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7972                                 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]);
7973                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7974                                 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]);
7975                 }
7976                 else
7977                 {
7978                         vec3_t ambientcolor;
7979                         float colorscale;
7980                         // set the color tint used for lights affecting this surface
7981                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7982                         colorscale = 2;
7983                         // q3bsp has no lightmap updates, so the lightstylevalue that
7984                         // would normally be baked into the lightmap must be
7985                         // applied to the color
7986                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7987                         if (model->type == mod_brushq3)
7988                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7989                         colorscale *= r_refdef.lightmapintensity;
7990                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7991                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7992                         // basic lit geometry
7993                         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]);
7994                         // add pants/shirt if needed
7995                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7996                                 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]);
7997                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7998                                 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]);
7999                         // now add ambient passes if needed
8000                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8001                         {
8002                                 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]);
8003                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8004                                         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]);
8005                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8006                                         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]);
8007                         }
8008                 }
8009                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8010                         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]);
8011                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8012                 {
8013                         // if this is opaque use alpha blend which will darken the earlier
8014                         // passes cheaply.
8015                         //
8016                         // if this is an alpha blended material, all the earlier passes
8017                         // were darkened by fog already, so we only need to add the fog
8018                         // color ontop through the fog mask texture
8019                         //
8020                         // if this is an additive blended material, all the earlier passes
8021                         // were darkened by fog already, and we should not add fog color
8022                         // (because the background was not darkened, there is no fog color
8023                         // that was lost behind it).
8024                         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]);
8025                 }
8026         }
8027
8028         return t->currentframe;
8029 }
8030
8031 rsurfacestate_t rsurface;
8032
8033 void RSurf_ActiveWorldEntity(void)
8034 {
8035         dp_model_t *model = r_refdef.scene.worldmodel;
8036         //if (rsurface.entity == r_refdef.scene.worldentity)
8037         //      return;
8038         rsurface.entity = r_refdef.scene.worldentity;
8039         rsurface.skeleton = NULL;
8040         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8041         rsurface.ent_skinnum = 0;
8042         rsurface.ent_qwskin = -1;
8043         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8044         rsurface.shadertime = r_refdef.scene.time;
8045         rsurface.matrix = identitymatrix;
8046         rsurface.inversematrix = identitymatrix;
8047         rsurface.matrixscale = 1;
8048         rsurface.inversematrixscale = 1;
8049         R_EntityMatrix(&identitymatrix);
8050         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8051         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8052         rsurface.fograngerecip = r_refdef.fograngerecip;
8053         rsurface.fogheightfade = r_refdef.fogheightfade;
8054         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8055         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8056         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8057         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8058         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8059         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8060         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8061         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8062         rsurface.colormod[3] = 1;
8063         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);
8064         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8065         rsurface.frameblend[0].lerp = 1;
8066         rsurface.ent_alttextures = false;
8067         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8068         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8069         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8070         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8071         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8072         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8073         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8074         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8075         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8076         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8077         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8078         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8079         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8080         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8081         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8082         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8083         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8084         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8085         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8086         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8087         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8088         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8089         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8090         rsurface.modelelement3i = model->surfmesh.data_element3i;
8091         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8092         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8093         rsurface.modelelement3s = model->surfmesh.data_element3s;
8094         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8095         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8096         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8097         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8098         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8099         rsurface.modelsurfaces = model->data_surfaces;
8100         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8101         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8102         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8103         rsurface.modelgeneratedvertex = false;
8104         rsurface.batchgeneratedvertex = false;
8105         rsurface.batchfirstvertex = 0;
8106         rsurface.batchnumvertices = 0;
8107         rsurface.batchfirsttriangle = 0;
8108         rsurface.batchnumtriangles = 0;
8109         rsurface.batchvertex3f  = NULL;
8110         rsurface.batchvertex3f_vertexbuffer = NULL;
8111         rsurface.batchvertex3f_bufferoffset = 0;
8112         rsurface.batchsvector3f = NULL;
8113         rsurface.batchsvector3f_vertexbuffer = NULL;
8114         rsurface.batchsvector3f_bufferoffset = 0;
8115         rsurface.batchtvector3f = NULL;
8116         rsurface.batchtvector3f_vertexbuffer = NULL;
8117         rsurface.batchtvector3f_bufferoffset = 0;
8118         rsurface.batchnormal3f  = NULL;
8119         rsurface.batchnormal3f_vertexbuffer = NULL;
8120         rsurface.batchnormal3f_bufferoffset = 0;
8121         rsurface.batchlightmapcolor4f = NULL;
8122         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8123         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8124         rsurface.batchtexcoordtexture2f = NULL;
8125         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8126         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8127         rsurface.batchtexcoordlightmap2f = NULL;
8128         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8129         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8130         rsurface.batchvertexmesh = NULL;
8131         rsurface.batchvertexmeshbuffer = NULL;
8132         rsurface.batchvertex3fbuffer = NULL;
8133         rsurface.batchelement3i = NULL;
8134         rsurface.batchelement3i_indexbuffer = NULL;
8135         rsurface.batchelement3i_bufferoffset = 0;
8136         rsurface.batchelement3s = NULL;
8137         rsurface.batchelement3s_indexbuffer = NULL;
8138         rsurface.batchelement3s_bufferoffset = 0;
8139         rsurface.passcolor4f = NULL;
8140         rsurface.passcolor4f_vertexbuffer = NULL;
8141         rsurface.passcolor4f_bufferoffset = 0;
8142 }
8143
8144 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8145 {
8146         dp_model_t *model = ent->model;
8147         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8148         //      return;
8149         rsurface.entity = (entity_render_t *)ent;
8150         rsurface.skeleton = ent->skeleton;
8151         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8152         rsurface.ent_skinnum = ent->skinnum;
8153         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;
8154         rsurface.ent_flags = ent->flags;
8155         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8156         rsurface.matrix = ent->matrix;
8157         rsurface.inversematrix = ent->inversematrix;
8158         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8159         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8160         R_EntityMatrix(&rsurface.matrix);
8161         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8162         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8163         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8164         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8165         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8166         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8167         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8168         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8169         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8170         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8171         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8172         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8173         rsurface.colormod[3] = ent->alpha;
8174         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8175         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8176         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8177         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8178         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8179         if (ent->model->brush.submodel && !prepass)
8180         {
8181                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8182                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8183         }
8184         if (model->surfmesh.isanimated && model->AnimateVertices)
8185         {
8186                 if (ent->animcache_vertex3f)
8187                 {
8188                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8189                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8190                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8191                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8192                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8193                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8194                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8195                 }
8196                 else if (wanttangents)
8197                 {
8198                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8199                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8200                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8201                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8202                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8203                         rsurface.modelvertexmesh = NULL;
8204                         rsurface.modelvertexmeshbuffer = NULL;
8205                         rsurface.modelvertex3fbuffer = NULL;
8206                 }
8207                 else if (wantnormals)
8208                 {
8209                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8210                         rsurface.modelsvector3f = NULL;
8211                         rsurface.modeltvector3f = NULL;
8212                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8213                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8214                         rsurface.modelvertexmesh = NULL;
8215                         rsurface.modelvertexmeshbuffer = NULL;
8216                         rsurface.modelvertex3fbuffer = NULL;
8217                 }
8218                 else
8219                 {
8220                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8221                         rsurface.modelsvector3f = NULL;
8222                         rsurface.modeltvector3f = NULL;
8223                         rsurface.modelnormal3f = NULL;
8224                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8225                         rsurface.modelvertexmesh = NULL;
8226                         rsurface.modelvertexmeshbuffer = NULL;
8227                         rsurface.modelvertex3fbuffer = NULL;
8228                 }
8229                 rsurface.modelvertex3f_vertexbuffer = 0;
8230                 rsurface.modelvertex3f_bufferoffset = 0;
8231                 rsurface.modelsvector3f_vertexbuffer = 0;
8232                 rsurface.modelsvector3f_bufferoffset = 0;
8233                 rsurface.modeltvector3f_vertexbuffer = 0;
8234                 rsurface.modeltvector3f_bufferoffset = 0;
8235                 rsurface.modelnormal3f_vertexbuffer = 0;
8236                 rsurface.modelnormal3f_bufferoffset = 0;
8237                 rsurface.modelgeneratedvertex = true;
8238         }
8239         else
8240         {
8241                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8242                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8243                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8244                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8245                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8246                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8247                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8248                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8249                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8250                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8251                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8252                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8253                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8254                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8255                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8256                 rsurface.modelgeneratedvertex = false;
8257         }
8258         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8259         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8260         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8261         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8262         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8263         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8264         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8265         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8266         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8267         rsurface.modelelement3i = model->surfmesh.data_element3i;
8268         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8269         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8270         rsurface.modelelement3s = model->surfmesh.data_element3s;
8271         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8272         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8273         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8274         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8275         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8276         rsurface.modelsurfaces = model->data_surfaces;
8277         rsurface.batchgeneratedvertex = false;
8278         rsurface.batchfirstvertex = 0;
8279         rsurface.batchnumvertices = 0;
8280         rsurface.batchfirsttriangle = 0;
8281         rsurface.batchnumtriangles = 0;
8282         rsurface.batchvertex3f  = NULL;
8283         rsurface.batchvertex3f_vertexbuffer = NULL;
8284         rsurface.batchvertex3f_bufferoffset = 0;
8285         rsurface.batchsvector3f = NULL;
8286         rsurface.batchsvector3f_vertexbuffer = NULL;
8287         rsurface.batchsvector3f_bufferoffset = 0;
8288         rsurface.batchtvector3f = NULL;
8289         rsurface.batchtvector3f_vertexbuffer = NULL;
8290         rsurface.batchtvector3f_bufferoffset = 0;
8291         rsurface.batchnormal3f  = NULL;
8292         rsurface.batchnormal3f_vertexbuffer = NULL;
8293         rsurface.batchnormal3f_bufferoffset = 0;
8294         rsurface.batchlightmapcolor4f = NULL;
8295         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8296         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8297         rsurface.batchtexcoordtexture2f = NULL;
8298         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8299         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8300         rsurface.batchtexcoordlightmap2f = NULL;
8301         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8302         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8303         rsurface.batchvertexmesh = NULL;
8304         rsurface.batchvertexmeshbuffer = NULL;
8305         rsurface.batchvertex3fbuffer = NULL;
8306         rsurface.batchelement3i = NULL;
8307         rsurface.batchelement3i_indexbuffer = NULL;
8308         rsurface.batchelement3i_bufferoffset = 0;
8309         rsurface.batchelement3s = NULL;
8310         rsurface.batchelement3s_indexbuffer = NULL;
8311         rsurface.batchelement3s_bufferoffset = 0;
8312         rsurface.passcolor4f = NULL;
8313         rsurface.passcolor4f_vertexbuffer = NULL;
8314         rsurface.passcolor4f_bufferoffset = 0;
8315 }
8316
8317 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)
8318 {
8319         rsurface.entity = r_refdef.scene.worldentity;
8320         rsurface.skeleton = NULL;
8321         rsurface.ent_skinnum = 0;
8322         rsurface.ent_qwskin = -1;
8323         rsurface.ent_flags = entflags;
8324         rsurface.shadertime = r_refdef.scene.time - shadertime;
8325         rsurface.modelnumvertices = numvertices;
8326         rsurface.modelnumtriangles = numtriangles;
8327         rsurface.matrix = *matrix;
8328         rsurface.inversematrix = *inversematrix;
8329         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8330         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8331         R_EntityMatrix(&rsurface.matrix);
8332         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8333         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8334         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8335         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8336         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8337         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8338         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8339         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8340         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8341         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8342         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8343         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8344         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);
8345         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8346         rsurface.frameblend[0].lerp = 1;
8347         rsurface.ent_alttextures = false;
8348         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8349         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8350         if (wanttangents)
8351         {
8352                 rsurface.modelvertex3f = (float *)vertex3f;
8353                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8354                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8355                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8356         }
8357         else if (wantnormals)
8358         {
8359                 rsurface.modelvertex3f = (float *)vertex3f;
8360                 rsurface.modelsvector3f = NULL;
8361                 rsurface.modeltvector3f = NULL;
8362                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8363         }
8364         else
8365         {
8366                 rsurface.modelvertex3f = (float *)vertex3f;
8367                 rsurface.modelsvector3f = NULL;
8368                 rsurface.modeltvector3f = NULL;
8369                 rsurface.modelnormal3f = NULL;
8370         }
8371         rsurface.modelvertexmesh = NULL;
8372         rsurface.modelvertexmeshbuffer = NULL;
8373         rsurface.modelvertex3fbuffer = NULL;
8374         rsurface.modelvertex3f_vertexbuffer = 0;
8375         rsurface.modelvertex3f_bufferoffset = 0;
8376         rsurface.modelsvector3f_vertexbuffer = 0;
8377         rsurface.modelsvector3f_bufferoffset = 0;
8378         rsurface.modeltvector3f_vertexbuffer = 0;
8379         rsurface.modeltvector3f_bufferoffset = 0;
8380         rsurface.modelnormal3f_vertexbuffer = 0;
8381         rsurface.modelnormal3f_bufferoffset = 0;
8382         rsurface.modelgeneratedvertex = true;
8383         rsurface.modellightmapcolor4f  = (float *)color4f;
8384         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8385         rsurface.modellightmapcolor4f_bufferoffset = 0;
8386         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8387         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8388         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8389         rsurface.modeltexcoordlightmap2f  = NULL;
8390         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8391         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8392         rsurface.modelelement3i = (int *)element3i;
8393         rsurface.modelelement3i_indexbuffer = NULL;
8394         rsurface.modelelement3i_bufferoffset = 0;
8395         rsurface.modelelement3s = (unsigned short *)element3s;
8396         rsurface.modelelement3s_indexbuffer = NULL;
8397         rsurface.modelelement3s_bufferoffset = 0;
8398         rsurface.modellightmapoffsets = NULL;
8399         rsurface.modelsurfaces = NULL;
8400         rsurface.batchgeneratedvertex = false;
8401         rsurface.batchfirstvertex = 0;
8402         rsurface.batchnumvertices = 0;
8403         rsurface.batchfirsttriangle = 0;
8404         rsurface.batchnumtriangles = 0;
8405         rsurface.batchvertex3f  = NULL;
8406         rsurface.batchvertex3f_vertexbuffer = NULL;
8407         rsurface.batchvertex3f_bufferoffset = 0;
8408         rsurface.batchsvector3f = NULL;
8409         rsurface.batchsvector3f_vertexbuffer = NULL;
8410         rsurface.batchsvector3f_bufferoffset = 0;
8411         rsurface.batchtvector3f = NULL;
8412         rsurface.batchtvector3f_vertexbuffer = NULL;
8413         rsurface.batchtvector3f_bufferoffset = 0;
8414         rsurface.batchnormal3f  = NULL;
8415         rsurface.batchnormal3f_vertexbuffer = NULL;
8416         rsurface.batchnormal3f_bufferoffset = 0;
8417         rsurface.batchlightmapcolor4f = NULL;
8418         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8419         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8420         rsurface.batchtexcoordtexture2f = NULL;
8421         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8422         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8423         rsurface.batchtexcoordlightmap2f = NULL;
8424         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8425         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8426         rsurface.batchvertexmesh = NULL;
8427         rsurface.batchvertexmeshbuffer = NULL;
8428         rsurface.batchvertex3fbuffer = NULL;
8429         rsurface.batchelement3i = NULL;
8430         rsurface.batchelement3i_indexbuffer = NULL;
8431         rsurface.batchelement3i_bufferoffset = 0;
8432         rsurface.batchelement3s = NULL;
8433         rsurface.batchelement3s_indexbuffer = NULL;
8434         rsurface.batchelement3s_bufferoffset = 0;
8435         rsurface.passcolor4f = NULL;
8436         rsurface.passcolor4f_vertexbuffer = NULL;
8437         rsurface.passcolor4f_bufferoffset = 0;
8438
8439         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8440         {
8441                 if ((wantnormals || wanttangents) && !normal3f)
8442                 {
8443                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8444                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8445                 }
8446                 if (wanttangents && !svector3f)
8447                 {
8448                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8449                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8450                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8451                 }
8452         }
8453 }
8454
8455 float RSurf_FogPoint(const float *v)
8456 {
8457         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8458         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8459         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8460         float FogHeightFade = r_refdef.fogheightfade;
8461         float fogfrac;
8462         unsigned int fogmasktableindex;
8463         if (r_refdef.fogplaneviewabove)
8464                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8465         else
8466                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8467         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8468         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8469 }
8470
8471 float RSurf_FogVertex(const float *v)
8472 {
8473         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8474         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8475         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8476         float FogHeightFade = rsurface.fogheightfade;
8477         float fogfrac;
8478         unsigned int fogmasktableindex;
8479         if (r_refdef.fogplaneviewabove)
8480                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8481         else
8482                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8483         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8484         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8485 }
8486
8487 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8488 {
8489         int i;
8490         for (i = 0;i < numelements;i++)
8491                 outelement3i[i] = inelement3i[i] + adjust;
8492 }
8493
8494 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8495 extern cvar_t gl_vbo;
8496 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8497 {
8498         int deformindex;
8499         int firsttriangle;
8500         int numtriangles;
8501         int firstvertex;
8502         int endvertex;
8503         int numvertices;
8504         int surfacefirsttriangle;
8505         int surfacenumtriangles;
8506         int surfacefirstvertex;
8507         int surfaceendvertex;
8508         int surfacenumvertices;
8509         int batchnumvertices;
8510         int batchnumtriangles;
8511         int needsupdate;
8512         int i, j;
8513         qboolean gaps;
8514         qboolean dynamicvertex;
8515         float amplitude;
8516         float animpos;
8517         float scale;
8518         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8519         float waveparms[4];
8520         q3shaderinfo_deform_t *deform;
8521         const msurface_t *surface, *firstsurface;
8522         r_vertexmesh_t *vertexmesh;
8523         if (!texturenumsurfaces)
8524                 return;
8525         // find vertex range of this surface batch
8526         gaps = false;
8527         firstsurface = texturesurfacelist[0];
8528         firsttriangle = firstsurface->num_firsttriangle;
8529         batchnumvertices = 0;
8530         batchnumtriangles = 0;
8531         firstvertex = endvertex = firstsurface->num_firstvertex;
8532         for (i = 0;i < texturenumsurfaces;i++)
8533         {
8534                 surface = texturesurfacelist[i];
8535                 if (surface != firstsurface + i)
8536                         gaps = true;
8537                 surfacefirstvertex = surface->num_firstvertex;
8538                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8539                 surfacenumvertices = surface->num_vertices;
8540                 surfacenumtriangles = surface->num_triangles;
8541                 if (firstvertex > surfacefirstvertex)
8542                         firstvertex = surfacefirstvertex;
8543                 if (endvertex < surfaceendvertex)
8544                         endvertex = surfaceendvertex;
8545                 batchnumvertices += surfacenumvertices;
8546                 batchnumtriangles += surfacenumtriangles;
8547         }
8548
8549         // we now know the vertex range used, and if there are any gaps in it
8550         rsurface.batchfirstvertex = firstvertex;
8551         rsurface.batchnumvertices = endvertex - firstvertex;
8552         rsurface.batchfirsttriangle = firsttriangle;
8553         rsurface.batchnumtriangles = batchnumtriangles;
8554
8555         // this variable holds flags for which properties have been updated that
8556         // may require regenerating vertexmesh array...
8557         needsupdate = 0;
8558
8559         // check if any dynamic vertex processing must occur
8560         dynamicvertex = false;
8561
8562         // if there is a chance of animated vertex colors, it's a dynamic batch
8563         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8564         {
8565                 dynamicvertex = true;
8566                 batchneed |= BATCHNEED_NOGAPS;
8567                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8568         }
8569
8570         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8571         {
8572                 switch (deform->deform)
8573                 {
8574                 default:
8575                 case Q3DEFORM_PROJECTIONSHADOW:
8576                 case Q3DEFORM_TEXT0:
8577                 case Q3DEFORM_TEXT1:
8578                 case Q3DEFORM_TEXT2:
8579                 case Q3DEFORM_TEXT3:
8580                 case Q3DEFORM_TEXT4:
8581                 case Q3DEFORM_TEXT5:
8582                 case Q3DEFORM_TEXT6:
8583                 case Q3DEFORM_TEXT7:
8584                 case Q3DEFORM_NONE:
8585                         break;
8586                 case Q3DEFORM_AUTOSPRITE:
8587                         dynamicvertex = true;
8588                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8589                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8590                         break;
8591                 case Q3DEFORM_AUTOSPRITE2:
8592                         dynamicvertex = true;
8593                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8594                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8595                         break;
8596                 case Q3DEFORM_NORMAL:
8597                         dynamicvertex = true;
8598                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8599                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8600                         break;
8601                 case Q3DEFORM_WAVE:
8602                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8603                                 break; // if wavefunc is a nop, ignore this transform
8604                         dynamicvertex = true;
8605                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8606                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8607                         break;
8608                 case Q3DEFORM_BULGE:
8609                         dynamicvertex = true;
8610                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8611                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8612                         break;
8613                 case Q3DEFORM_MOVE:
8614                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8615                                 break; // if wavefunc is a nop, ignore this transform
8616                         dynamicvertex = true;
8617                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8618                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8619                         break;
8620                 }
8621         }
8622         switch(rsurface.texture->tcgen.tcgen)
8623         {
8624         default:
8625         case Q3TCGEN_TEXTURE:
8626                 break;
8627         case Q3TCGEN_LIGHTMAP:
8628                 dynamicvertex = true;
8629                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8630                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8631                 break;
8632         case Q3TCGEN_VECTOR:
8633                 dynamicvertex = true;
8634                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8635                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8636                 break;
8637         case Q3TCGEN_ENVIRONMENT:
8638                 dynamicvertex = true;
8639                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8640                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8641                 break;
8642         }
8643         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8644         {
8645                 dynamicvertex = true;
8646                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8647                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8648         }
8649
8650         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8651         {
8652                 dynamicvertex = true;
8653                 batchneed |= BATCHNEED_NOGAPS;
8654                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8655         }
8656
8657         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8658         {
8659                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8660                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8661                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8662                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8663                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8664                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8665                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8666         }
8667
8668         // when the model data has no vertex buffer (dynamic mesh), we need to
8669         // eliminate gaps
8670         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8671                 batchneed |= BATCHNEED_NOGAPS;
8672
8673         // if needsupdate, we have to do a dynamic vertex batch for sure
8674         if (needsupdate & batchneed)
8675                 dynamicvertex = true;
8676
8677         // see if we need to build vertexmesh from arrays
8678         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8679                 dynamicvertex = true;
8680
8681         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8682         // also some drivers strongly dislike firstvertex
8683         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8684                 dynamicvertex = true;
8685
8686         rsurface.batchvertex3f = rsurface.modelvertex3f;
8687         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8688         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8689         rsurface.batchsvector3f = rsurface.modelsvector3f;
8690         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8691         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8692         rsurface.batchtvector3f = rsurface.modeltvector3f;
8693         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8694         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8695         rsurface.batchnormal3f = rsurface.modelnormal3f;
8696         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8697         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8698         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8699         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8700         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8701         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8702         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8703         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8704         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8705         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8706         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8707         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8708         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8709         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8710         rsurface.batchelement3i = rsurface.modelelement3i;
8711         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8712         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8713         rsurface.batchelement3s = rsurface.modelelement3s;
8714         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8715         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8716
8717         // if any dynamic vertex processing has to occur in software, we copy the
8718         // entire surface list together before processing to rebase the vertices
8719         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8720         //
8721         // if any gaps exist and we do not have a static vertex buffer, we have to
8722         // copy the surface list together to avoid wasting upload bandwidth on the
8723         // vertices in the gaps.
8724         //
8725         // if gaps exist and we have a static vertex buffer, we still have to
8726         // combine the index buffer ranges into one dynamic index buffer.
8727         //
8728         // in all cases we end up with data that can be drawn in one call.
8729
8730         if (!dynamicvertex)
8731         {
8732                 // static vertex data, just set pointers...
8733                 rsurface.batchgeneratedvertex = false;
8734                 // if there are gaps, we want to build a combined index buffer,
8735                 // otherwise use the original static buffer with an appropriate offset
8736                 if (gaps)
8737                 {
8738                         // build a new triangle elements array for this batch
8739                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8740                         rsurface.batchfirsttriangle = 0;
8741                         numtriangles = 0;
8742                         for (i = 0;i < texturenumsurfaces;i++)
8743                         {
8744                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8745                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8746                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8747                                 numtriangles += surfacenumtriangles;
8748                         }
8749                         rsurface.batchelement3i_indexbuffer = NULL;
8750                         rsurface.batchelement3i_bufferoffset = 0;
8751                         rsurface.batchelement3s = NULL;
8752                         rsurface.batchelement3s_indexbuffer = NULL;
8753                         rsurface.batchelement3s_bufferoffset = 0;
8754                         if (endvertex <= 65536)
8755                         {
8756                                 // make a 16bit (unsigned short) index array if possible
8757                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8758                                 for (i = 0;i < numtriangles*3;i++)
8759                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8760                         }
8761                 }
8762                 return;
8763         }
8764
8765         // something needs software processing, do it for real...
8766         // we only directly handle separate array data in this case and then
8767         // generate interleaved data if needed...
8768         rsurface.batchgeneratedvertex = true;
8769
8770         // now copy the vertex data into a combined array and make an index array
8771         // (this is what Quake3 does all the time)
8772         //if (gaps || rsurface.batchfirstvertex)
8773         {
8774                 rsurface.batchvertex3fbuffer = NULL;
8775                 rsurface.batchvertexmesh = NULL;
8776                 rsurface.batchvertexmeshbuffer = NULL;
8777                 rsurface.batchvertex3f = NULL;
8778                 rsurface.batchvertex3f_vertexbuffer = NULL;
8779                 rsurface.batchvertex3f_bufferoffset = 0;
8780                 rsurface.batchsvector3f = NULL;
8781                 rsurface.batchsvector3f_vertexbuffer = NULL;
8782                 rsurface.batchsvector3f_bufferoffset = 0;
8783                 rsurface.batchtvector3f = NULL;
8784                 rsurface.batchtvector3f_vertexbuffer = NULL;
8785                 rsurface.batchtvector3f_bufferoffset = 0;
8786                 rsurface.batchnormal3f = NULL;
8787                 rsurface.batchnormal3f_vertexbuffer = NULL;
8788                 rsurface.batchnormal3f_bufferoffset = 0;
8789                 rsurface.batchlightmapcolor4f = NULL;
8790                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8791                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8792                 rsurface.batchtexcoordtexture2f = NULL;
8793                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8794                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8795                 rsurface.batchtexcoordlightmap2f = NULL;
8796                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8797                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8798                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8799                 rsurface.batchelement3i_indexbuffer = NULL;
8800                 rsurface.batchelement3i_bufferoffset = 0;
8801                 rsurface.batchelement3s = NULL;
8802                 rsurface.batchelement3s_indexbuffer = NULL;
8803                 rsurface.batchelement3s_bufferoffset = 0;
8804                 // we'll only be setting up certain arrays as needed
8805                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8806                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8807                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8808                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8809                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8810                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8811                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8812                 {
8813                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8814                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8815                 }
8816                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8817                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8818                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8819                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8820                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8821                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8822                 numvertices = 0;
8823                 numtriangles = 0;
8824                 for (i = 0;i < texturenumsurfaces;i++)
8825                 {
8826                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8827                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8828                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8829                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8830                         // copy only the data requested
8831                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8832                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8833                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8834                         {
8835                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8836                                 {
8837                                         if (rsurface.batchvertex3f)
8838                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8839                                         else
8840                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8841                                 }
8842                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8843                                 {
8844                                         if (rsurface.modelnormal3f)
8845                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8846                                         else
8847                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8848                                 }
8849                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8850                                 {
8851                                         if (rsurface.modelsvector3f)
8852                                         {
8853                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8854                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8855                                         }
8856                                         else
8857                                         {
8858                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8859                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8860                                         }
8861                                 }
8862                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8863                                 {
8864                                         if (rsurface.modellightmapcolor4f)
8865                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8866                                         else
8867                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8868                                 }
8869                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8870                                 {
8871                                         if (rsurface.modeltexcoordtexture2f)
8872                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8873                                         else
8874                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8875                                 }
8876                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8877                                 {
8878                                         if (rsurface.modeltexcoordlightmap2f)
8879                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8880                                         else
8881                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8882                                 }
8883                         }
8884                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8885                         numvertices += surfacenumvertices;
8886                         numtriangles += surfacenumtriangles;
8887                 }
8888
8889                 // generate a 16bit index array as well if possible
8890                 // (in general, dynamic batches fit)
8891                 if (numvertices <= 65536)
8892                 {
8893                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8894                         for (i = 0;i < numtriangles*3;i++)
8895                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8896                 }
8897
8898                 // since we've copied everything, the batch now starts at 0
8899                 rsurface.batchfirstvertex = 0;
8900                 rsurface.batchnumvertices = batchnumvertices;
8901                 rsurface.batchfirsttriangle = 0;
8902                 rsurface.batchnumtriangles = batchnumtriangles;
8903         }
8904
8905         // q1bsp surfaces rendered in vertex color mode have to have colors
8906         // calculated based on lightstyles
8907         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8908         {
8909                 // generate color arrays for the surfaces in this list
8910                 int c[4];
8911                 int scale;
8912                 int size3;
8913                 const int *offsets;
8914                 const unsigned char *lm;
8915                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8916                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8917                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8918                 numvertices = 0;
8919                 for (i = 0;i < texturenumsurfaces;i++)
8920                 {
8921                         surface = texturesurfacelist[i];
8922                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8923                         surfacenumvertices = surface->num_vertices;
8924                         if (surface->lightmapinfo->samples)
8925                         {
8926                                 for (j = 0;j < surfacenumvertices;j++)
8927                                 {
8928                                         lm = surface->lightmapinfo->samples + offsets[j];
8929                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8930                                         VectorScale(lm, scale, c);
8931                                         if (surface->lightmapinfo->styles[1] != 255)
8932                                         {
8933                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8934                                                 lm += size3;
8935                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8936                                                 VectorMA(c, scale, lm, c);
8937                                                 if (surface->lightmapinfo->styles[2] != 255)
8938                                                 {
8939                                                         lm += size3;
8940                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8941                                                         VectorMA(c, scale, lm, c);
8942                                                         if (surface->lightmapinfo->styles[3] != 255)
8943                                                         {
8944                                                                 lm += size3;
8945                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8946                                                                 VectorMA(c, scale, lm, c);
8947                                                         }
8948                                                 }
8949                                         }
8950                                         c[0] >>= 7;
8951                                         c[1] >>= 7;
8952                                         c[2] >>= 7;
8953                                         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);
8954                                         numvertices++;
8955                                 }
8956                         }
8957                         else
8958                         {
8959                                 for (j = 0;j < surfacenumvertices;j++)
8960                                 {
8961                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8962                                         numvertices++;
8963                                 }
8964                         }
8965                 }
8966         }
8967
8968         // if vertices are deformed (sprite flares and things in maps, possibly
8969         // water waves, bulges and other deformations), modify the copied vertices
8970         // in place
8971         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8972         {
8973                 switch (deform->deform)
8974                 {
8975                 default:
8976                 case Q3DEFORM_PROJECTIONSHADOW:
8977                 case Q3DEFORM_TEXT0:
8978                 case Q3DEFORM_TEXT1:
8979                 case Q3DEFORM_TEXT2:
8980                 case Q3DEFORM_TEXT3:
8981                 case Q3DEFORM_TEXT4:
8982                 case Q3DEFORM_TEXT5:
8983                 case Q3DEFORM_TEXT6:
8984                 case Q3DEFORM_TEXT7:
8985                 case Q3DEFORM_NONE:
8986                         break;
8987                 case Q3DEFORM_AUTOSPRITE:
8988                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8989                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8990                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8991                         VectorNormalize(newforward);
8992                         VectorNormalize(newright);
8993                         VectorNormalize(newup);
8994 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8995 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8996 //                      rsurface.batchvertex3f_bufferoffset = 0;
8997 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8998 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8999 //                      rsurface.batchsvector3f_bufferoffset = 0;
9000 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9001 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9002 //                      rsurface.batchtvector3f_bufferoffset = 0;
9003 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9004 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9005 //                      rsurface.batchnormal3f_bufferoffset = 0;
9006                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9007                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9008                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9009                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9010                                 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);
9011                         // a single autosprite surface can contain multiple sprites...
9012                         for (j = 0;j < batchnumvertices - 3;j += 4)
9013                         {
9014                                 VectorClear(center);
9015                                 for (i = 0;i < 4;i++)
9016                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9017                                 VectorScale(center, 0.25f, center);
9018                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9019                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9020                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9021                                 for (i = 0;i < 4;i++)
9022                                 {
9023                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9024                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9025                                 }
9026                         }
9027                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9028                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9029                         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);
9030                         break;
9031                 case Q3DEFORM_AUTOSPRITE2:
9032                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9033                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9034                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9035                         VectorNormalize(newforward);
9036                         VectorNormalize(newright);
9037                         VectorNormalize(newup);
9038 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9039 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9040 //                      rsurface.batchvertex3f_bufferoffset = 0;
9041                         {
9042                                 const float *v1, *v2;
9043                                 vec3_t start, end;
9044                                 float f, l;
9045                                 struct
9046                                 {
9047                                         float length2;
9048                                         const float *v1;
9049                                         const float *v2;
9050                                 }
9051                                 shortest[2];
9052                                 memset(shortest, 0, sizeof(shortest));
9053                                 // a single autosprite surface can contain multiple sprites...
9054                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9055                                 {
9056                                         VectorClear(center);
9057                                         for (i = 0;i < 4;i++)
9058                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9059                                         VectorScale(center, 0.25f, center);
9060                                         // find the two shortest edges, then use them to define the
9061                                         // axis vectors for rotating around the central axis
9062                                         for (i = 0;i < 6;i++)
9063                                         {
9064                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9065                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9066                                                 l = VectorDistance2(v1, v2);
9067                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9068                                                 if (v1[2] != v2[2])
9069                                                         l += (1.0f / 1024.0f);
9070                                                 if (shortest[0].length2 > l || i == 0)
9071                                                 {
9072                                                         shortest[1] = shortest[0];
9073                                                         shortest[0].length2 = l;
9074                                                         shortest[0].v1 = v1;
9075                                                         shortest[0].v2 = v2;
9076                                                 }
9077                                                 else if (shortest[1].length2 > l || i == 1)
9078                                                 {
9079                                                         shortest[1].length2 = l;
9080                                                         shortest[1].v1 = v1;
9081                                                         shortest[1].v2 = v2;
9082                                                 }
9083                                         }
9084                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9085                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9086                                         // this calculates the right vector from the shortest edge
9087                                         // and the up vector from the edge midpoints
9088                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9089                                         VectorNormalize(right);
9090                                         VectorSubtract(end, start, up);
9091                                         VectorNormalize(up);
9092                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9093                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9094                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9095                                         VectorNegate(forward, forward);
9096                                         VectorReflect(forward, 0, up, forward);
9097                                         VectorNormalize(forward);
9098                                         CrossProduct(up, forward, newright);
9099                                         VectorNormalize(newright);
9100                                         // rotate the quad around the up axis vector, this is made
9101                                         // especially easy by the fact we know the quad is flat,
9102                                         // so we only have to subtract the center position and
9103                                         // measure distance along the right vector, and then
9104                                         // multiply that by the newright vector and add back the
9105                                         // center position
9106                                         // we also need to subtract the old position to undo the
9107                                         // displacement from the center, which we do with a
9108                                         // DotProduct, the subtraction/addition of center is also
9109                                         // optimized into DotProducts here
9110                                         l = DotProduct(right, center);
9111                                         for (i = 0;i < 4;i++)
9112                                         {
9113                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9114                                                 f = DotProduct(right, v1) - l;
9115                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9116                                         }
9117                                 }
9118                         }
9119                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9120                         {
9121 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9122 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9123 //                              rsurface.batchnormal3f_bufferoffset = 0;
9124                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9125                         }
9126                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9127                         {
9128 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9129 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9130 //                              rsurface.batchsvector3f_bufferoffset = 0;
9131 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9132 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9133 //                              rsurface.batchtvector3f_bufferoffset = 0;
9134                                 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);
9135                         }
9136                         break;
9137                 case Q3DEFORM_NORMAL:
9138                         // deform the normals to make reflections wavey
9139                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9140                         rsurface.batchnormal3f_vertexbuffer = NULL;
9141                         rsurface.batchnormal3f_bufferoffset = 0;
9142                         for (j = 0;j < batchnumvertices;j++)
9143                         {
9144                                 float vertex[3];
9145                                 float *normal = rsurface.batchnormal3f + 3*j;
9146                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9147                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9148                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9149                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9150                                 VectorNormalize(normal);
9151                         }
9152                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9153                         {
9154 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9155 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9156 //                              rsurface.batchsvector3f_bufferoffset = 0;
9157 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9158 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9159 //                              rsurface.batchtvector3f_bufferoffset = 0;
9160                                 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);
9161                         }
9162                         break;
9163                 case Q3DEFORM_WAVE:
9164                         // deform vertex array to make wavey water and flags and such
9165                         waveparms[0] = deform->waveparms[0];
9166                         waveparms[1] = deform->waveparms[1];
9167                         waveparms[2] = deform->waveparms[2];
9168                         waveparms[3] = deform->waveparms[3];
9169                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9170                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9171                         // this is how a divisor of vertex influence on deformation
9172                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9173                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9174 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9175 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9176 //                      rsurface.batchvertex3f_bufferoffset = 0;
9177 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9178 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9179 //                      rsurface.batchnormal3f_bufferoffset = 0;
9180                         for (j = 0;j < batchnumvertices;j++)
9181                         {
9182                                 // if the wavefunc depends on time, evaluate it per-vertex
9183                                 if (waveparms[3])
9184                                 {
9185                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9186                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9187                                 }
9188                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9189                         }
9190                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9191                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9192                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9193                         {
9194 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9195 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9196 //                              rsurface.batchsvector3f_bufferoffset = 0;
9197 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9198 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9199 //                              rsurface.batchtvector3f_bufferoffset = 0;
9200                                 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);
9201                         }
9202                         break;
9203                 case Q3DEFORM_BULGE:
9204                         // deform vertex array to make the surface have moving bulges
9205 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9206 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9207 //                      rsurface.batchvertex3f_bufferoffset = 0;
9208 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9209 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9210 //                      rsurface.batchnormal3f_bufferoffset = 0;
9211                         for (j = 0;j < batchnumvertices;j++)
9212                         {
9213                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9214                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9215                         }
9216                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9217                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9218                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9219                         {
9220 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9221 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9222 //                              rsurface.batchsvector3f_bufferoffset = 0;
9223 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9224 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9225 //                              rsurface.batchtvector3f_bufferoffset = 0;
9226                                 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);
9227                         }
9228                         break;
9229                 case Q3DEFORM_MOVE:
9230                         // deform vertex array
9231                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9232                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9233                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9234                         VectorScale(deform->parms, scale, waveparms);
9235 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9236 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9237 //                      rsurface.batchvertex3f_bufferoffset = 0;
9238                         for (j = 0;j < batchnumvertices;j++)
9239                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9240                         break;
9241                 }
9242         }
9243
9244         // generate texcoords based on the chosen texcoord source
9245         switch(rsurface.texture->tcgen.tcgen)
9246         {
9247         default:
9248         case Q3TCGEN_TEXTURE:
9249                 break;
9250         case Q3TCGEN_LIGHTMAP:
9251 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9252 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9253 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9254                 if (rsurface.batchtexcoordlightmap2f)
9255                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9256                 break;
9257         case Q3TCGEN_VECTOR:
9258 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9259 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9260 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9261                 for (j = 0;j < batchnumvertices;j++)
9262                 {
9263                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9264                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9265                 }
9266                 break;
9267         case Q3TCGEN_ENVIRONMENT:
9268                 // make environment reflections using a spheremap
9269                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9270                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9271                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9272                 for (j = 0;j < batchnumvertices;j++)
9273                 {
9274                         // identical to Q3A's method, but executed in worldspace so
9275                         // carried models can be shiny too
9276
9277                         float viewer[3], d, reflected[3], worldreflected[3];
9278
9279                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9280                         // VectorNormalize(viewer);
9281
9282                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9283
9284                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9285                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9286                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9287                         // note: this is proportinal to viewer, so we can normalize later
9288
9289                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9290                         VectorNormalize(worldreflected);
9291
9292                         // note: this sphere map only uses world x and z!
9293                         // so positive and negative y will LOOK THE SAME.
9294                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9295                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9296                 }
9297                 break;
9298         }
9299         // the only tcmod that needs software vertex processing is turbulent, so
9300         // check for it here and apply the changes if needed
9301         // and we only support that as the first one
9302         // (handling a mixture of turbulent and other tcmods would be problematic
9303         //  without punting it entirely to a software path)
9304         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9305         {
9306                 amplitude = rsurface.texture->tcmods[0].parms[1];
9307                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9308 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9309 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9310 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9311                 for (j = 0;j < batchnumvertices;j++)
9312                 {
9313                         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);
9314                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9315                 }
9316         }
9317
9318         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9319         {
9320                 // convert the modified arrays to vertex structs
9321 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9322 //              rsurface.batchvertexmeshbuffer = NULL;
9323                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9324                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9325                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9326                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9327                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9328                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9329                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9330                 {
9331                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9332                         {
9333                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9334                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9335                         }
9336                 }
9337                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9338                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9339                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9340                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9341                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9342                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9343                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9344                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9345                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9346         }
9347 }
9348
9349 void RSurf_DrawBatch(void)
9350 {
9351         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9352         // through the pipeline, killing it earlier in the pipeline would have
9353         // per-surface overhead rather than per-batch overhead, so it's best to
9354         // reject it here, before it hits glDraw.
9355         if (rsurface.batchnumtriangles == 0)
9356                 return;
9357 #if 0
9358         // batch debugging code
9359         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9360         {
9361                 int i;
9362                 int j;
9363                 int c;
9364                 const int *e;
9365                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9366                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9367                 {
9368                         c = e[i];
9369                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9370                         {
9371                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9372                                 {
9373                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9374                                                 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);
9375                                         break;
9376                                 }
9377                         }
9378                 }
9379         }
9380 #endif
9381         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);
9382 }
9383
9384 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9385 {
9386         // pick the closest matching water plane
9387         int planeindex, vertexindex, bestplaneindex = -1;
9388         float d, bestd;
9389         vec3_t vert;
9390         const float *v;
9391         r_waterstate_waterplane_t *p;
9392         qboolean prepared = false;
9393         bestd = 0;
9394         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9395         {
9396                 if(p->camera_entity != rsurface.texture->camera_entity)
9397                         continue;
9398                 d = 0;
9399                 if(!prepared)
9400                 {
9401                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9402                         prepared = true;
9403                         if(rsurface.batchnumvertices == 0)
9404                                 break;
9405                 }
9406                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9407                 {
9408                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9409                         d += fabs(PlaneDiff(vert, &p->plane));
9410                 }
9411                 if (bestd > d || bestplaneindex < 0)
9412                 {
9413                         bestd = d;
9414                         bestplaneindex = planeindex;
9415                 }
9416         }
9417         return bestplaneindex;
9418         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9419         // this situation though, as it might be better to render single larger
9420         // batches with useless stuff (backface culled for example) than to
9421         // render multiple smaller batches
9422 }
9423
9424 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9425 {
9426         int i;
9427         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9428         rsurface.passcolor4f_vertexbuffer = 0;
9429         rsurface.passcolor4f_bufferoffset = 0;
9430         for (i = 0;i < rsurface.batchnumvertices;i++)
9431                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9432 }
9433
9434 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9435 {
9436         int i;
9437         float f;
9438         const float *v;
9439         const float *c;
9440         float *c2;
9441         if (rsurface.passcolor4f)
9442         {
9443                 // generate color arrays
9444                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9445                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9446                 rsurface.passcolor4f_vertexbuffer = 0;
9447                 rsurface.passcolor4f_bufferoffset = 0;
9448                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9449                 {
9450                         f = RSurf_FogVertex(v);
9451                         c2[0] = c[0] * f;
9452                         c2[1] = c[1] * f;
9453                         c2[2] = c[2] * f;
9454                         c2[3] = c[3];
9455                 }
9456         }
9457         else
9458         {
9459                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9460                 rsurface.passcolor4f_vertexbuffer = 0;
9461                 rsurface.passcolor4f_bufferoffset = 0;
9462                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9463                 {
9464                         f = RSurf_FogVertex(v);
9465                         c2[0] = f;
9466                         c2[1] = f;
9467                         c2[2] = f;
9468                         c2[3] = 1;
9469                 }
9470         }
9471 }
9472
9473 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9474 {
9475         int i;
9476         float f;
9477         const float *v;
9478         const float *c;
9479         float *c2;
9480         if (!rsurface.passcolor4f)
9481                 return;
9482         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9483         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9484         rsurface.passcolor4f_vertexbuffer = 0;
9485         rsurface.passcolor4f_bufferoffset = 0;
9486         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)
9487         {
9488                 f = RSurf_FogVertex(v);
9489                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9490                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9491                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9492                 c2[3] = c[3];
9493         }
9494 }
9495
9496 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9497 {
9498         int i;
9499         const float *c;
9500         float *c2;
9501         if (!rsurface.passcolor4f)
9502                 return;
9503         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9504         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9505         rsurface.passcolor4f_vertexbuffer = 0;
9506         rsurface.passcolor4f_bufferoffset = 0;
9507         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9508         {
9509                 c2[0] = c[0] * r;
9510                 c2[1] = c[1] * g;
9511                 c2[2] = c[2] * b;
9512                 c2[3] = c[3] * a;
9513         }
9514 }
9515
9516 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9517 {
9518         int i;
9519         const float *c;
9520         float *c2;
9521         if (!rsurface.passcolor4f)
9522                 return;
9523         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9524         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9525         rsurface.passcolor4f_vertexbuffer = 0;
9526         rsurface.passcolor4f_bufferoffset = 0;
9527         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9528         {
9529                 c2[0] = c[0] + r_refdef.scene.ambient;
9530                 c2[1] = c[1] + r_refdef.scene.ambient;
9531                 c2[2] = c[2] + r_refdef.scene.ambient;
9532                 c2[3] = c[3];
9533         }
9534 }
9535
9536 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9537 {
9538         // TODO: optimize
9539         rsurface.passcolor4f = NULL;
9540         rsurface.passcolor4f_vertexbuffer = 0;
9541         rsurface.passcolor4f_bufferoffset = 0;
9542         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9543         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9544         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9545         GL_Color(r, g, b, a);
9546         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9547         RSurf_DrawBatch();
9548 }
9549
9550 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9551 {
9552         // TODO: optimize applyfog && applycolor case
9553         // just apply fog if necessary, and tint the fog color array if necessary
9554         rsurface.passcolor4f = NULL;
9555         rsurface.passcolor4f_vertexbuffer = 0;
9556         rsurface.passcolor4f_bufferoffset = 0;
9557         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9558         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9559         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9560         GL_Color(r, g, b, a);
9561         RSurf_DrawBatch();
9562 }
9563
9564 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9565 {
9566         // TODO: optimize
9567         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9568         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9569         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9570         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9571         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9572         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9573         GL_Color(r, g, b, a);
9574         RSurf_DrawBatch();
9575 }
9576
9577 static void RSurf_DrawBatch_GL11_ClampColor(void)
9578 {
9579         int i;
9580         const float *c1;
9581         float *c2;
9582         if (!rsurface.passcolor4f)
9583                 return;
9584         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9585         {
9586                 c2[0] = bound(0.0f, c1[0], 1.0f);
9587                 c2[1] = bound(0.0f, c1[1], 1.0f);
9588                 c2[2] = bound(0.0f, c1[2], 1.0f);
9589                 c2[3] = bound(0.0f, c1[3], 1.0f);
9590         }
9591 }
9592
9593 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9594 {
9595         int i;
9596         float f;
9597         const float *v;
9598         const float *n;
9599         float *c;
9600         //vec3_t eyedir;
9601
9602         // fake shading
9603         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9604         rsurface.passcolor4f_vertexbuffer = 0;
9605         rsurface.passcolor4f_bufferoffset = 0;
9606         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)
9607         {
9608                 f = -DotProduct(r_refdef.view.forward, n);
9609                 f = max(0, f);
9610                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9611                 f *= r_refdef.lightmapintensity;
9612                 Vector4Set(c, f, f, f, 1);
9613         }
9614 }
9615
9616 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9617 {
9618         RSurf_DrawBatch_GL11_ApplyFakeLight();
9619         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9620         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9621         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9622         GL_Color(r, g, b, a);
9623         RSurf_DrawBatch();
9624 }
9625
9626 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9627 {
9628         int i;
9629         float f;
9630         float alpha;
9631         const float *v;
9632         const float *n;
9633         float *c;
9634         vec3_t ambientcolor;
9635         vec3_t diffusecolor;
9636         vec3_t lightdir;
9637         // TODO: optimize
9638         // model lighting
9639         VectorCopy(rsurface.modellight_lightdir, lightdir);
9640         f = 0.5f * r_refdef.lightmapintensity;
9641         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9642         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9643         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9644         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9645         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9646         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9647         alpha = *a;
9648         if (VectorLength2(diffusecolor) > 0)
9649         {
9650                 // q3-style directional shading
9651                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9652                 rsurface.passcolor4f_vertexbuffer = 0;
9653                 rsurface.passcolor4f_bufferoffset = 0;
9654                 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)
9655                 {
9656                         if ((f = DotProduct(n, lightdir)) > 0)
9657                                 VectorMA(ambientcolor, f, diffusecolor, c);
9658                         else
9659                                 VectorCopy(ambientcolor, c);
9660                         c[3] = alpha;
9661                 }
9662                 *r = 1;
9663                 *g = 1;
9664                 *b = 1;
9665                 *a = 1;
9666                 *applycolor = false;
9667         }
9668         else
9669         {
9670                 *r = ambientcolor[0];
9671                 *g = ambientcolor[1];
9672                 *b = ambientcolor[2];
9673                 rsurface.passcolor4f = NULL;
9674                 rsurface.passcolor4f_vertexbuffer = 0;
9675                 rsurface.passcolor4f_bufferoffset = 0;
9676         }
9677 }
9678
9679 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9680 {
9681         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9682         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9683         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9684         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9685         GL_Color(r, g, b, a);
9686         RSurf_DrawBatch();
9687 }
9688
9689 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9690 {
9691         int i;
9692         float f;
9693         const float *v;
9694         float *c;
9695
9696         // fake shading
9697         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9698         rsurface.passcolor4f_vertexbuffer = 0;
9699         rsurface.passcolor4f_bufferoffset = 0;
9700
9701         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9702         {
9703                 f = 1 - RSurf_FogVertex(v);
9704                 c[0] = r;
9705                 c[1] = g;
9706                 c[2] = b;
9707                 c[3] = f * a;
9708         }
9709 }
9710
9711 void RSurf_SetupDepthAndCulling(void)
9712 {
9713         // submodels are biased to avoid z-fighting with world surfaces that they
9714         // may be exactly overlapping (avoids z-fighting artifacts on certain
9715         // doors and things in Quake maps)
9716         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9717         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9718         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9719         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9720 }
9721
9722 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9723 {
9724         // transparent sky would be ridiculous
9725         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9726                 return;
9727         R_SetupShader_Generic_NoTexture(false, false);
9728         skyrenderlater = true;
9729         RSurf_SetupDepthAndCulling();
9730         GL_DepthMask(true);
9731         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9732         // skymasking on them, and Quake3 never did sky masking (unlike
9733         // software Quake and software Quake2), so disable the sky masking
9734         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9735         // and skymasking also looks very bad when noclipping outside the
9736         // level, so don't use it then either.
9737         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9738         {
9739                 R_Mesh_ResetTextureState();
9740                 if (skyrendermasked)
9741                 {
9742                         R_SetupShader_DepthOrShadow(false, false);
9743                         // depth-only (masking)
9744                         GL_ColorMask(0,0,0,0);
9745                         // just to make sure that braindead drivers don't draw
9746                         // anything despite that colormask...
9747                         GL_BlendFunc(GL_ZERO, GL_ONE);
9748                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9749                         if (rsurface.batchvertex3fbuffer)
9750                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9751                         else
9752                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9753                 }
9754                 else
9755                 {
9756                         R_SetupShader_Generic_NoTexture(false, false);
9757                         // fog sky
9758                         GL_BlendFunc(GL_ONE, GL_ZERO);
9759                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9760                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9761                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9762                 }
9763                 RSurf_DrawBatch();
9764                 if (skyrendermasked)
9765                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9766         }
9767         R_Mesh_ResetTextureState();
9768         GL_Color(1, 1, 1, 1);
9769 }
9770
9771 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9772 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9773 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9774 {
9775         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9776                 return;
9777         if (prepass)
9778         {
9779                 // render screenspace normalmap to texture
9780                 GL_DepthMask(true);
9781                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9782                 RSurf_DrawBatch();
9783                 return;
9784         }
9785
9786         // bind lightmap texture
9787
9788         // water/refraction/reflection/camera surfaces have to be handled specially
9789         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9790         {
9791                 int start, end, startplaneindex;
9792                 for (start = 0;start < texturenumsurfaces;start = end)
9793                 {
9794                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9795                         if(startplaneindex < 0)
9796                         {
9797                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9798                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9799                                 end = start + 1;
9800                                 continue;
9801                         }
9802                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9803                                 ;
9804                         // now that we have a batch using the same planeindex, render it
9805                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9806                         {
9807                                 // render water or distortion background
9808                                 GL_DepthMask(true);
9809                                 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);
9810                                 RSurf_DrawBatch();
9811                                 // blend surface on top
9812                                 GL_DepthMask(false);
9813                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9814                                 RSurf_DrawBatch();
9815                         }
9816                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9817                         {
9818                                 // render surface with reflection texture as input
9819                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9820                                 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);
9821                                 RSurf_DrawBatch();
9822                         }
9823                 }
9824                 return;
9825         }
9826
9827         // render surface batch normally
9828         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9829         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);
9830         RSurf_DrawBatch();
9831 }
9832
9833 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9834 {
9835         // OpenGL 1.3 path - anything not completely ancient
9836         qboolean applycolor;
9837         qboolean applyfog;
9838         int layerindex;
9839         const texturelayer_t *layer;
9840         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);
9841         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9842
9843         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9844         {
9845                 vec4_t layercolor;
9846                 int layertexrgbscale;
9847                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9848                 {
9849                         if (layerindex == 0)
9850                                 GL_AlphaTest(true);
9851                         else
9852                         {
9853                                 GL_AlphaTest(false);
9854                                 GL_DepthFunc(GL_EQUAL);
9855                         }
9856                 }
9857                 GL_DepthMask(layer->depthmask && writedepth);
9858                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9859                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9860                 {
9861                         layertexrgbscale = 4;
9862                         VectorScale(layer->color, 0.25f, layercolor);
9863                 }
9864                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9865                 {
9866                         layertexrgbscale = 2;
9867                         VectorScale(layer->color, 0.5f, layercolor);
9868                 }
9869                 else
9870                 {
9871                         layertexrgbscale = 1;
9872                         VectorScale(layer->color, 1.0f, layercolor);
9873                 }
9874                 layercolor[3] = layer->color[3];
9875                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9876                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9877                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9878                 switch (layer->type)
9879                 {
9880                 case TEXTURELAYERTYPE_LITTEXTURE:
9881                         // single-pass lightmapped texture with 2x rgbscale
9882                         R_Mesh_TexBind(0, r_texture_white);
9883                         R_Mesh_TexMatrix(0, NULL);
9884                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9885                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9886                         R_Mesh_TexBind(1, layer->texture);
9887                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9888                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9889                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9890                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9891                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9892                         else if (FAKELIGHT_ENABLED)
9893                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9894                         else if (rsurface.uselightmaptexture)
9895                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9896                         else
9897                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9898                         break;
9899                 case TEXTURELAYERTYPE_TEXTURE:
9900                         // singletexture unlit texture with transparency support
9901                         R_Mesh_TexBind(0, layer->texture);
9902                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9903                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9904                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9905                         R_Mesh_TexBind(1, 0);
9906                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9907                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9908                         break;
9909                 case TEXTURELAYERTYPE_FOG:
9910                         // singletexture fogging
9911                         if (layer->texture)
9912                         {
9913                                 R_Mesh_TexBind(0, layer->texture);
9914                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9915                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9916                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9917                         }
9918                         else
9919                         {
9920                                 R_Mesh_TexBind(0, 0);
9921                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9922                         }
9923                         R_Mesh_TexBind(1, 0);
9924                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9925                         // generate a color array for the fog pass
9926                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9927                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9928                         RSurf_DrawBatch();
9929                         break;
9930                 default:
9931                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9932                 }
9933         }
9934         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9935         {
9936                 GL_DepthFunc(GL_LEQUAL);
9937                 GL_AlphaTest(false);
9938         }
9939 }
9940
9941 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9942 {
9943         // OpenGL 1.1 - crusty old voodoo path
9944         qboolean applyfog;
9945         int layerindex;
9946         const texturelayer_t *layer;
9947         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);
9948         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9949
9950         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9951         {
9952                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9953                 {
9954                         if (layerindex == 0)
9955                                 GL_AlphaTest(true);
9956                         else
9957                         {
9958                                 GL_AlphaTest(false);
9959                                 GL_DepthFunc(GL_EQUAL);
9960                         }
9961                 }
9962                 GL_DepthMask(layer->depthmask && writedepth);
9963                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9964                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9965                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9966                 switch (layer->type)
9967                 {
9968                 case TEXTURELAYERTYPE_LITTEXTURE:
9969                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9970                         {
9971                                 // two-pass lit texture with 2x rgbscale
9972                                 // first the lightmap pass
9973                                 R_Mesh_TexBind(0, r_texture_white);
9974                                 R_Mesh_TexMatrix(0, NULL);
9975                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9976                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9977                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9978                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9979                                 else if (FAKELIGHT_ENABLED)
9980                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9981                                 else if (rsurface.uselightmaptexture)
9982                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9983                                 else
9984                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9985                                 // then apply the texture to it
9986                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9987                                 R_Mesh_TexBind(0, layer->texture);
9988                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9989                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9990                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9991                                 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);
9992                         }
9993                         else
9994                         {
9995                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9996                                 R_Mesh_TexBind(0, layer->texture);
9997                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9998                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9999                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10000                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10001                                         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);
10002                                 else
10003                                         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);
10004                         }
10005                         break;
10006                 case TEXTURELAYERTYPE_TEXTURE:
10007                         // singletexture unlit texture with transparency support
10008                         R_Mesh_TexBind(0, layer->texture);
10009                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10010                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10011                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10012                         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);
10013                         break;
10014                 case TEXTURELAYERTYPE_FOG:
10015                         // singletexture fogging
10016                         if (layer->texture)
10017                         {
10018                                 R_Mesh_TexBind(0, layer->texture);
10019                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10020                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10021                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10022                         }
10023                         else
10024                         {
10025                                 R_Mesh_TexBind(0, 0);
10026                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10027                         }
10028                         // generate a color array for the fog pass
10029                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10030                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10031                         RSurf_DrawBatch();
10032                         break;
10033                 default:
10034                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10035                 }
10036         }
10037         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10038         {
10039                 GL_DepthFunc(GL_LEQUAL);
10040                 GL_AlphaTest(false);
10041         }
10042 }
10043
10044 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10045 {
10046         int vi;
10047         int j;
10048         r_vertexgeneric_t *batchvertex;
10049         float c[4];
10050
10051 //      R_Mesh_ResetTextureState();
10052         R_SetupShader_Generic_NoTexture(false, false);
10053
10054         if(rsurface.texture && rsurface.texture->currentskinframe)
10055         {
10056                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10057                 c[3] *= rsurface.texture->currentalpha;
10058         }
10059         else
10060         {
10061                 c[0] = 1;
10062                 c[1] = 0;
10063                 c[2] = 1;
10064                 c[3] = 1;
10065         }
10066
10067         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10068         {
10069                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10070                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10071                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10072         }
10073
10074         // brighten it up (as texture value 127 means "unlit")
10075         c[0] *= 2 * r_refdef.view.colorscale;
10076         c[1] *= 2 * r_refdef.view.colorscale;
10077         c[2] *= 2 * r_refdef.view.colorscale;
10078
10079         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10080                 c[3] *= r_wateralpha.value;
10081
10082         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10083         {
10084                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10085                 GL_DepthMask(false);
10086         }
10087         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10088         {
10089                 GL_BlendFunc(GL_ONE, GL_ONE);
10090                 GL_DepthMask(false);
10091         }
10092         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10093         {
10094                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10095                 GL_DepthMask(false);
10096         }
10097         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10098         {
10099                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10100                 GL_DepthMask(false);
10101         }
10102         else
10103         {
10104                 GL_BlendFunc(GL_ONE, GL_ZERO);
10105                 GL_DepthMask(writedepth);
10106         }
10107
10108         if (r_showsurfaces.integer == 3)
10109         {
10110                 rsurface.passcolor4f = NULL;
10111
10112                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10113                 {
10114                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10115
10116                         rsurface.passcolor4f = NULL;
10117                         rsurface.passcolor4f_vertexbuffer = 0;
10118                         rsurface.passcolor4f_bufferoffset = 0;
10119                 }
10120                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10121                 {
10122                         qboolean applycolor = true;
10123                         float one = 1.0;
10124
10125                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10126
10127                         r_refdef.lightmapintensity = 1;
10128                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10129                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10130                 }
10131                 else if (FAKELIGHT_ENABLED)
10132                 {
10133                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10134
10135                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10136                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10137                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10138                 }
10139                 else
10140                 {
10141                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10142
10143                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10144                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10145                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10146                 }
10147
10148                 if(!rsurface.passcolor4f)
10149                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10150
10151                 RSurf_DrawBatch_GL11_ApplyAmbient();
10152                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10153                 if(r_refdef.fogenabled)
10154                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10155                 RSurf_DrawBatch_GL11_ClampColor();
10156
10157                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10158                 R_SetupShader_Generic_NoTexture(false, false);
10159                 RSurf_DrawBatch();
10160         }
10161         else if (!r_refdef.view.showdebug)
10162         {
10163                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10164                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10165                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10166                 {
10167                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10168                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10169                 }
10170                 R_Mesh_PrepareVertices_Generic_Unlock();
10171                 RSurf_DrawBatch();
10172         }
10173         else if (r_showsurfaces.integer == 4)
10174         {
10175                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10176                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10177                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10178                 {
10179                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10180                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10181                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10182                 }
10183                 R_Mesh_PrepareVertices_Generic_Unlock();
10184                 RSurf_DrawBatch();
10185         }
10186         else if (r_showsurfaces.integer == 2)
10187         {
10188                 const int *e;
10189                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10190                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10191                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10192                 {
10193                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10194                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10195                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10196                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10197                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10198                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10199                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10200                 }
10201                 R_Mesh_PrepareVertices_Generic_Unlock();
10202                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10203         }
10204         else
10205         {
10206                 int texturesurfaceindex;
10207                 int k;
10208                 const msurface_t *surface;
10209                 float surfacecolor4f[4];
10210                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10211                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10212                 vi = 0;
10213                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10214                 {
10215                         surface = texturesurfacelist[texturesurfaceindex];
10216                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10217                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10218                         for (j = 0;j < surface->num_vertices;j++)
10219                         {
10220                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10221                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10222                                 vi++;
10223                         }
10224                 }
10225                 R_Mesh_PrepareVertices_Generic_Unlock();
10226                 RSurf_DrawBatch();
10227         }
10228 }
10229
10230 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10231 {
10232         CHECKGLERROR
10233         RSurf_SetupDepthAndCulling();
10234         if (r_showsurfaces.integer)
10235         {
10236                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10237                 return;
10238         }
10239         switch (vid.renderpath)
10240         {
10241         case RENDERPATH_GL20:
10242         case RENDERPATH_D3D9:
10243         case RENDERPATH_D3D10:
10244         case RENDERPATH_D3D11:
10245         case RENDERPATH_SOFT:
10246         case RENDERPATH_GLES2:
10247                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10248                 break;
10249         case RENDERPATH_GL13:
10250         case RENDERPATH_GLES1:
10251                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10252                 break;
10253         case RENDERPATH_GL11:
10254                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10255                 break;
10256         }
10257         CHECKGLERROR
10258 }
10259
10260 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10261 {
10262         CHECKGLERROR
10263         RSurf_SetupDepthAndCulling();
10264         if (r_showsurfaces.integer)
10265         {
10266                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10267                 return;
10268         }
10269         switch (vid.renderpath)
10270         {
10271         case RENDERPATH_GL20:
10272         case RENDERPATH_D3D9:
10273         case RENDERPATH_D3D10:
10274         case RENDERPATH_D3D11:
10275         case RENDERPATH_SOFT:
10276         case RENDERPATH_GLES2:
10277                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10278                 break;
10279         case RENDERPATH_GL13:
10280         case RENDERPATH_GLES1:
10281                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10282                 break;
10283         case RENDERPATH_GL11:
10284                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10285                 break;
10286         }
10287         CHECKGLERROR
10288 }
10289
10290 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10291 {
10292         int i, j;
10293         int texturenumsurfaces, endsurface;
10294         texture_t *texture;
10295         const msurface_t *surface;
10296         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10297
10298         // if the model is static it doesn't matter what value we give for
10299         // wantnormals and wanttangents, so this logic uses only rules applicable
10300         // to a model, knowing that they are meaningless otherwise
10301         if (ent == r_refdef.scene.worldentity)
10302                 RSurf_ActiveWorldEntity();
10303         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10304                 RSurf_ActiveModelEntity(ent, false, false, false);
10305         else
10306         {
10307                 switch (vid.renderpath)
10308                 {
10309                 case RENDERPATH_GL20:
10310                 case RENDERPATH_D3D9:
10311                 case RENDERPATH_D3D10:
10312                 case RENDERPATH_D3D11:
10313                 case RENDERPATH_SOFT:
10314                 case RENDERPATH_GLES2:
10315                         RSurf_ActiveModelEntity(ent, true, true, false);
10316                         break;
10317                 case RENDERPATH_GL11:
10318                 case RENDERPATH_GL13:
10319                 case RENDERPATH_GLES1:
10320                         RSurf_ActiveModelEntity(ent, true, false, false);
10321                         break;
10322                 }
10323         }
10324
10325         if (r_transparentdepthmasking.integer)
10326         {
10327                 qboolean setup = false;
10328                 for (i = 0;i < numsurfaces;i = j)
10329                 {
10330                         j = i + 1;
10331                         surface = rsurface.modelsurfaces + surfacelist[i];
10332                         texture = surface->texture;
10333                         rsurface.texture = R_GetCurrentTexture(texture);
10334                         rsurface.lightmaptexture = NULL;
10335                         rsurface.deluxemaptexture = NULL;
10336                         rsurface.uselightmaptexture = false;
10337                         // scan ahead until we find a different texture
10338                         endsurface = min(i + 1024, numsurfaces);
10339                         texturenumsurfaces = 0;
10340                         texturesurfacelist[texturenumsurfaces++] = surface;
10341                         for (;j < endsurface;j++)
10342                         {
10343                                 surface = rsurface.modelsurfaces + surfacelist[j];
10344                                 if (texture != surface->texture)
10345                                         break;
10346                                 texturesurfacelist[texturenumsurfaces++] = surface;
10347                         }
10348                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10349                                 continue;
10350                         // render the range of surfaces as depth
10351                         if (!setup)
10352                         {
10353                                 setup = true;
10354                                 GL_ColorMask(0,0,0,0);
10355                                 GL_Color(1,1,1,1);
10356                                 GL_DepthTest(true);
10357                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10358                                 GL_DepthMask(true);
10359 //                              R_Mesh_ResetTextureState();
10360                                 R_SetupShader_DepthOrShadow(false, false);
10361                         }
10362                         RSurf_SetupDepthAndCulling();
10363                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10364                         if (rsurface.batchvertex3fbuffer)
10365                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10366                         else
10367                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10368                         RSurf_DrawBatch();
10369                 }
10370                 if (setup)
10371                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10372         }
10373
10374         for (i = 0;i < numsurfaces;i = j)
10375         {
10376                 j = i + 1;
10377                 surface = rsurface.modelsurfaces + surfacelist[i];
10378                 texture = surface->texture;
10379                 rsurface.texture = R_GetCurrentTexture(texture);
10380                 // scan ahead until we find a different texture
10381                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10382                 texturenumsurfaces = 0;
10383                 texturesurfacelist[texturenumsurfaces++] = surface;
10384                 if(FAKELIGHT_ENABLED)
10385                 {
10386                         rsurface.lightmaptexture = NULL;
10387                         rsurface.deluxemaptexture = NULL;
10388                         rsurface.uselightmaptexture = false;
10389                         for (;j < endsurface;j++)
10390                         {
10391                                 surface = rsurface.modelsurfaces + surfacelist[j];
10392                                 if (texture != surface->texture)
10393                                         break;
10394                                 texturesurfacelist[texturenumsurfaces++] = surface;
10395                         }
10396                 }
10397                 else
10398                 {
10399                         rsurface.lightmaptexture = surface->lightmaptexture;
10400                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10401                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10402                         for (;j < endsurface;j++)
10403                         {
10404                                 surface = rsurface.modelsurfaces + surfacelist[j];
10405                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10406                                         break;
10407                                 texturesurfacelist[texturenumsurfaces++] = surface;
10408                         }
10409                 }
10410                 // render the range of surfaces
10411                 if (ent == r_refdef.scene.worldentity)
10412                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10413                 else
10414                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10415         }
10416         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10417 }
10418
10419 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10420 {
10421         // transparent surfaces get pushed off into the transparent queue
10422         int surfacelistindex;
10423         const msurface_t *surface;
10424         vec3_t tempcenter, center;
10425         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10426         {
10427                 surface = texturesurfacelist[surfacelistindex];
10428                 if (r_transparent_sortsurfacesbynearest.integer)
10429                 {
10430                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10431                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10432                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10433                 }
10434                 else
10435                 {
10436                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10437                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10438                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10439                 }
10440                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10441                 if (rsurface.entity->transparent_offset) // transparent offset
10442                 {
10443                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10444                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10445                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10446                 }
10447                 R_MeshQueue_AddTransparent((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : ((rsurface.entity->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : MESHQUEUE_SORT_DISTANCE), center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10448         }
10449 }
10450
10451 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10452 {
10453         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10454                 return;
10455         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10456                 return;
10457         RSurf_SetupDepthAndCulling();
10458         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10459         if (rsurface.batchvertex3fbuffer)
10460                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10461         else
10462                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10463         RSurf_DrawBatch();
10464 }
10465
10466 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10467 {
10468         CHECKGLERROR
10469         if (depthonly)
10470                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10471         else if (prepass)
10472         {
10473                 if (!rsurface.texture->currentnumlayers)
10474                         return;
10475                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10476                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10477                 else
10478                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10479         }
10480         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10481                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10482         else if (!rsurface.texture->currentnumlayers)
10483                 return;
10484         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10485         {
10486                 // in the deferred case, transparent surfaces were queued during prepass
10487                 if (!r_shadow_usingdeferredprepass)
10488                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10489         }
10490         else
10491         {
10492                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10493                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10494         }
10495         CHECKGLERROR
10496 }
10497
10498 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10499 {
10500         int i, j;
10501         texture_t *texture;
10502         R_FrameData_SetMark();
10503         // break the surface list down into batches by texture and use of lightmapping
10504         for (i = 0;i < numsurfaces;i = j)
10505         {
10506                 j = i + 1;
10507                 // texture is the base texture pointer, rsurface.texture is the
10508                 // current frame/skin the texture is directing us to use (for example
10509                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10510                 // use skin 1 instead)
10511                 texture = surfacelist[i]->texture;
10512                 rsurface.texture = R_GetCurrentTexture(texture);
10513                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10514                 {
10515                         // if this texture is not the kind we want, skip ahead to the next one
10516                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10517                                 ;
10518                         continue;
10519                 }
10520                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10521                 {
10522                         rsurface.lightmaptexture = NULL;
10523                         rsurface.deluxemaptexture = NULL;
10524                         rsurface.uselightmaptexture = false;
10525                         // simply scan ahead until we find a different texture or lightmap state
10526                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10527                                 ;
10528                 }
10529                 else
10530                 {
10531                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10532                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10533                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10534                         // simply scan ahead until we find a different texture or lightmap state
10535                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10536                                 ;
10537                 }
10538                 // render the range of surfaces
10539                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10540         }
10541         R_FrameData_ReturnToMark();
10542 }
10543
10544 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10545 {
10546         CHECKGLERROR
10547         if (depthonly)
10548                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10549         else if (prepass)
10550         {
10551                 if (!rsurface.texture->currentnumlayers)
10552                         return;
10553                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10554                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10555                 else
10556                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10557         }
10558         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10559                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10560         else if (!rsurface.texture->currentnumlayers)
10561                 return;
10562         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10563         {
10564                 // in the deferred case, transparent surfaces were queued during prepass
10565                 if (!r_shadow_usingdeferredprepass)
10566                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10567         }
10568         else
10569         {
10570                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10571                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10572         }
10573         CHECKGLERROR
10574 }
10575
10576 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10577 {
10578         int i, j;
10579         texture_t *texture;
10580         R_FrameData_SetMark();
10581         // break the surface list down into batches by texture and use of lightmapping
10582         for (i = 0;i < numsurfaces;i = j)
10583         {
10584                 j = i + 1;
10585                 // texture is the base texture pointer, rsurface.texture is the
10586                 // current frame/skin the texture is directing us to use (for example
10587                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10588                 // use skin 1 instead)
10589                 texture = surfacelist[i]->texture;
10590                 rsurface.texture = R_GetCurrentTexture(texture);
10591                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10592                 {
10593                         // if this texture is not the kind we want, skip ahead to the next one
10594                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10595                                 ;
10596                         continue;
10597                 }
10598                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10599                 {
10600                         rsurface.lightmaptexture = NULL;
10601                         rsurface.deluxemaptexture = NULL;
10602                         rsurface.uselightmaptexture = false;
10603                         // simply scan ahead until we find a different texture or lightmap state
10604                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10605                                 ;
10606                 }
10607                 else
10608                 {
10609                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10610                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10611                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10612                         // simply scan ahead until we find a different texture or lightmap state
10613                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10614                                 ;
10615                 }
10616                 // render the range of surfaces
10617                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10618         }
10619         R_FrameData_ReturnToMark();
10620 }
10621
10622 float locboxvertex3f[6*4*3] =
10623 {
10624         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10625         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10626         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10627         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10628         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10629         1,0,0, 0,0,0, 0,1,0, 1,1,0
10630 };
10631
10632 unsigned short locboxelements[6*2*3] =
10633 {
10634          0, 1, 2, 0, 2, 3,
10635          4, 5, 6, 4, 6, 7,
10636          8, 9,10, 8,10,11,
10637         12,13,14, 12,14,15,
10638         16,17,18, 16,18,19,
10639         20,21,22, 20,22,23
10640 };
10641
10642 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10643 {
10644         int i, j;
10645         cl_locnode_t *loc = (cl_locnode_t *)ent;
10646         vec3_t mins, size;
10647         float vertex3f[6*4*3];
10648         CHECKGLERROR
10649         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10650         GL_DepthMask(false);
10651         GL_DepthRange(0, 1);
10652         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10653         GL_DepthTest(true);
10654         GL_CullFace(GL_NONE);
10655         R_EntityMatrix(&identitymatrix);
10656
10657 //      R_Mesh_ResetTextureState();
10658
10659         i = surfacelist[0];
10660         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10661                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10662                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10663                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10664
10665         if (VectorCompare(loc->mins, loc->maxs))
10666         {
10667                 VectorSet(size, 2, 2, 2);
10668                 VectorMA(loc->mins, -0.5f, size, mins);
10669         }
10670         else
10671         {
10672                 VectorCopy(loc->mins, mins);
10673                 VectorSubtract(loc->maxs, loc->mins, size);
10674         }
10675
10676         for (i = 0;i < 6*4*3;)
10677                 for (j = 0;j < 3;j++, i++)
10678                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10679
10680         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10681         R_SetupShader_Generic_NoTexture(false, false);
10682         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10683 }
10684
10685 void R_DrawLocs(void)
10686 {
10687         int index;
10688         cl_locnode_t *loc, *nearestloc;
10689         vec3_t center;
10690         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10691         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10692         {
10693                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10694                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10695         }
10696 }
10697
10698 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10699 {
10700         if (decalsystem->decals)
10701                 Mem_Free(decalsystem->decals);
10702         memset(decalsystem, 0, sizeof(*decalsystem));
10703 }
10704
10705 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)
10706 {
10707         tridecal_t *decal;
10708         tridecal_t *decals;
10709         int i;
10710
10711         // expand or initialize the system
10712         if (decalsystem->maxdecals <= decalsystem->numdecals)
10713         {
10714                 decalsystem_t old = *decalsystem;
10715                 qboolean useshortelements;
10716                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10717                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10718                 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)));
10719                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10720                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10721                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10722                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10723                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10724                 if (decalsystem->numdecals)
10725                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10726                 if (old.decals)
10727                         Mem_Free(old.decals);
10728                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10729                         decalsystem->element3i[i] = i;
10730                 if (useshortelements)
10731                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10732                                 decalsystem->element3s[i] = i;
10733         }
10734
10735         // grab a decal and search for another free slot for the next one
10736         decals = decalsystem->decals;
10737         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10738         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10739                 ;
10740         decalsystem->freedecal = i;
10741         if (decalsystem->numdecals <= i)
10742                 decalsystem->numdecals = i + 1;
10743
10744         // initialize the decal
10745         decal->lived = 0;
10746         decal->triangleindex = triangleindex;
10747         decal->surfaceindex = surfaceindex;
10748         decal->decalsequence = decalsequence;
10749         decal->color4f[0][0] = c0[0];
10750         decal->color4f[0][1] = c0[1];
10751         decal->color4f[0][2] = c0[2];
10752         decal->color4f[0][3] = 1;
10753         decal->color4f[1][0] = c1[0];
10754         decal->color4f[1][1] = c1[1];
10755         decal->color4f[1][2] = c1[2];
10756         decal->color4f[1][3] = 1;
10757         decal->color4f[2][0] = c2[0];
10758         decal->color4f[2][1] = c2[1];
10759         decal->color4f[2][2] = c2[2];
10760         decal->color4f[2][3] = 1;
10761         decal->vertex3f[0][0] = v0[0];
10762         decal->vertex3f[0][1] = v0[1];
10763         decal->vertex3f[0][2] = v0[2];
10764         decal->vertex3f[1][0] = v1[0];
10765         decal->vertex3f[1][1] = v1[1];
10766         decal->vertex3f[1][2] = v1[2];
10767         decal->vertex3f[2][0] = v2[0];
10768         decal->vertex3f[2][1] = v2[1];
10769         decal->vertex3f[2][2] = v2[2];
10770         decal->texcoord2f[0][0] = t0[0];
10771         decal->texcoord2f[0][1] = t0[1];
10772         decal->texcoord2f[1][0] = t1[0];
10773         decal->texcoord2f[1][1] = t1[1];
10774         decal->texcoord2f[2][0] = t2[0];
10775         decal->texcoord2f[2][1] = t2[1];
10776         TriangleNormal(v0, v1, v2, decal->plane);
10777         VectorNormalize(decal->plane);
10778         decal->plane[3] = DotProduct(v0, decal->plane);
10779 }
10780
10781 extern cvar_t cl_decals_bias;
10782 extern cvar_t cl_decals_models;
10783 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10784 // baseparms, parms, temps
10785 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)
10786 {
10787         int cornerindex;
10788         int index;
10789         float v[9][3];
10790         const float *vertex3f;
10791         const float *normal3f;
10792         int numpoints;
10793         float points[2][9][3];
10794         float temp[3];
10795         float tc[9][2];
10796         float f;
10797         float c[9][4];
10798         const int *e;
10799
10800         e = rsurface.modelelement3i + 3*triangleindex;
10801
10802         vertex3f = rsurface.modelvertex3f;
10803         normal3f = rsurface.modelnormal3f;
10804
10805         if (normal3f)
10806         {
10807                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10808                 {
10809                         index = 3*e[cornerindex];
10810                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10811                 }
10812         }
10813         else
10814         {
10815                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10816                 {
10817                         index = 3*e[cornerindex];
10818                         VectorCopy(vertex3f + index, v[cornerindex]);
10819                 }
10820         }
10821
10822         // cull backfaces
10823         //TriangleNormal(v[0], v[1], v[2], normal);
10824         //if (DotProduct(normal, localnormal) < 0.0f)
10825         //      continue;
10826         // clip by each of the box planes formed from the projection matrix
10827         // if anything survives, we emit the decal
10828         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]);
10829         if (numpoints < 3)
10830                 return;
10831         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]);
10832         if (numpoints < 3)
10833                 return;
10834         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]);
10835         if (numpoints < 3)
10836                 return;
10837         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]);
10838         if (numpoints < 3)
10839                 return;
10840         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]);
10841         if (numpoints < 3)
10842                 return;
10843         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]);
10844         if (numpoints < 3)
10845                 return;
10846         // some part of the triangle survived, so we have to accept it...
10847         if (dynamic)
10848         {
10849                 // dynamic always uses the original triangle
10850                 numpoints = 3;
10851                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10852                 {
10853                         index = 3*e[cornerindex];
10854                         VectorCopy(vertex3f + index, v[cornerindex]);
10855                 }
10856         }
10857         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10858         {
10859                 // convert vertex positions to texcoords
10860                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10861                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10862                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10863                 // calculate distance fade from the projection origin
10864                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10865                 f = bound(0.0f, f, 1.0f);
10866                 c[cornerindex][0] = r * f;
10867                 c[cornerindex][1] = g * f;
10868                 c[cornerindex][2] = b * f;
10869                 c[cornerindex][3] = 1.0f;
10870                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10871         }
10872         if (dynamic)
10873                 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);
10874         else
10875                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10876                         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);
10877 }
10878 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)
10879 {
10880         matrix4x4_t projection;
10881         decalsystem_t *decalsystem;
10882         qboolean dynamic;
10883         dp_model_t *model;
10884         const msurface_t *surface;
10885         const msurface_t *surfaces;
10886         const int *surfacelist;
10887         const texture_t *texture;
10888         int numtriangles;
10889         int numsurfacelist;
10890         int surfacelistindex;
10891         int surfaceindex;
10892         int triangleindex;
10893         float localorigin[3];
10894         float localnormal[3];
10895         float localmins[3];
10896         float localmaxs[3];
10897         float localsize;
10898         //float normal[3];
10899         float planes[6][4];
10900         float angles[3];
10901         bih_t *bih;
10902         int bih_triangles_count;
10903         int bih_triangles[256];
10904         int bih_surfaces[256];
10905
10906         decalsystem = &ent->decalsystem;
10907         model = ent->model;
10908         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10909         {
10910                 R_DecalSystem_Reset(&ent->decalsystem);
10911                 return;
10912         }
10913
10914         if (!model->brush.data_leafs && !cl_decals_models.integer)
10915         {
10916                 if (decalsystem->model)
10917                         R_DecalSystem_Reset(decalsystem);
10918                 return;
10919         }
10920
10921         if (decalsystem->model != model)
10922                 R_DecalSystem_Reset(decalsystem);
10923         decalsystem->model = model;
10924
10925         RSurf_ActiveModelEntity(ent, true, false, false);
10926
10927         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10928         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10929         VectorNormalize(localnormal);
10930         localsize = worldsize*rsurface.inversematrixscale;
10931         localmins[0] = localorigin[0] - localsize;
10932         localmins[1] = localorigin[1] - localsize;
10933         localmins[2] = localorigin[2] - localsize;
10934         localmaxs[0] = localorigin[0] + localsize;
10935         localmaxs[1] = localorigin[1] + localsize;
10936         localmaxs[2] = localorigin[2] + localsize;
10937
10938         //VectorCopy(localnormal, planes[4]);
10939         //VectorVectors(planes[4], planes[2], planes[0]);
10940         AnglesFromVectors(angles, localnormal, NULL, false);
10941         AngleVectors(angles, planes[0], planes[2], planes[4]);
10942         VectorNegate(planes[0], planes[1]);
10943         VectorNegate(planes[2], planes[3]);
10944         VectorNegate(planes[4], planes[5]);
10945         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10946         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10947         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10948         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10949         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10950         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10951
10952 #if 1
10953 // works
10954 {
10955         matrix4x4_t forwardprojection;
10956         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10957         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10958 }
10959 #else
10960 // broken
10961 {
10962         float projectionvector[4][3];
10963         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10964         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10965         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10966         projectionvector[0][0] = planes[0][0] * ilocalsize;
10967         projectionvector[0][1] = planes[1][0] * ilocalsize;
10968         projectionvector[0][2] = planes[2][0] * ilocalsize;
10969         projectionvector[1][0] = planes[0][1] * ilocalsize;
10970         projectionvector[1][1] = planes[1][1] * ilocalsize;
10971         projectionvector[1][2] = planes[2][1] * ilocalsize;
10972         projectionvector[2][0] = planes[0][2] * ilocalsize;
10973         projectionvector[2][1] = planes[1][2] * ilocalsize;
10974         projectionvector[2][2] = planes[2][2] * ilocalsize;
10975         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10976         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10977         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10978         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10979 }
10980 #endif
10981
10982         dynamic = model->surfmesh.isanimated;
10983         numsurfacelist = model->nummodelsurfaces;
10984         surfacelist = model->sortedmodelsurfaces;
10985         surfaces = model->data_surfaces;
10986
10987         bih = NULL;
10988         bih_triangles_count = -1;
10989         if(!dynamic)
10990         {
10991                 if(model->render_bih.numleafs)
10992                         bih = &model->render_bih;
10993                 else if(model->collision_bih.numleafs)
10994                         bih = &model->collision_bih;
10995         }
10996         if(bih)
10997                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10998         if(bih_triangles_count == 0)
10999                 return;
11000         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11001                 return;
11002         if(bih_triangles_count > 0)
11003         {
11004                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11005                 {
11006                         surfaceindex = bih_surfaces[triangleindex];
11007                         surface = surfaces + surfaceindex;
11008                         texture = surface->texture;
11009                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11010                                 continue;
11011                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11012                                 continue;
11013                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11014                 }
11015         }
11016         else
11017         {
11018                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11019                 {
11020                         surfaceindex = surfacelist[surfacelistindex];
11021                         surface = surfaces + surfaceindex;
11022                         // check cull box first because it rejects more than any other check
11023                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11024                                 continue;
11025                         // skip transparent surfaces
11026                         texture = surface->texture;
11027                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11028                                 continue;
11029                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11030                                 continue;
11031                         numtriangles = surface->num_triangles;
11032                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11033                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11034                 }
11035         }
11036 }
11037
11038 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11039 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)
11040 {
11041         int renderentityindex;
11042         float worldmins[3];
11043         float worldmaxs[3];
11044         entity_render_t *ent;
11045
11046         if (!cl_decals_newsystem.integer)
11047                 return;
11048
11049         worldmins[0] = worldorigin[0] - worldsize;
11050         worldmins[1] = worldorigin[1] - worldsize;
11051         worldmins[2] = worldorigin[2] - worldsize;
11052         worldmaxs[0] = worldorigin[0] + worldsize;
11053         worldmaxs[1] = worldorigin[1] + worldsize;
11054         worldmaxs[2] = worldorigin[2] + worldsize;
11055
11056         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11057
11058         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11059         {
11060                 ent = r_refdef.scene.entities[renderentityindex];
11061                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11062                         continue;
11063
11064                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11065         }
11066 }
11067
11068 typedef struct r_decalsystem_splatqueue_s
11069 {
11070         vec3_t worldorigin;
11071         vec3_t worldnormal;
11072         float color[4];
11073         float tcrange[4];
11074         float worldsize;
11075         int decalsequence;
11076 }
11077 r_decalsystem_splatqueue_t;
11078
11079 int r_decalsystem_numqueued = 0;
11080 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11081
11082 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)
11083 {
11084         r_decalsystem_splatqueue_t *queue;
11085
11086         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11087                 return;
11088
11089         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11090         VectorCopy(worldorigin, queue->worldorigin);
11091         VectorCopy(worldnormal, queue->worldnormal);
11092         Vector4Set(queue->color, r, g, b, a);
11093         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11094         queue->worldsize = worldsize;
11095         queue->decalsequence = cl.decalsequence++;
11096 }
11097
11098 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11099 {
11100         int i;
11101         r_decalsystem_splatqueue_t *queue;
11102
11103         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11104                 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);
11105         r_decalsystem_numqueued = 0;
11106 }
11107
11108 extern cvar_t cl_decals_max;
11109 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11110 {
11111         int i;
11112         decalsystem_t *decalsystem = &ent->decalsystem;
11113         int numdecals;
11114         int killsequence;
11115         tridecal_t *decal;
11116         float frametime;
11117         float lifetime;
11118
11119         if (!decalsystem->numdecals)
11120                 return;
11121
11122         if (r_showsurfaces.integer)
11123                 return;
11124
11125         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11126         {
11127                 R_DecalSystem_Reset(decalsystem);
11128                 return;
11129         }
11130
11131         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11132         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11133
11134         if (decalsystem->lastupdatetime)
11135                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11136         else
11137                 frametime = 0;
11138         decalsystem->lastupdatetime = r_refdef.scene.time;
11139         decal = decalsystem->decals;
11140         numdecals = decalsystem->numdecals;
11141
11142         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11143         {
11144                 if (decal->color4f[0][3])
11145                 {
11146                         decal->lived += frametime;
11147                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11148                         {
11149                                 memset(decal, 0, sizeof(*decal));
11150                                 if (decalsystem->freedecal > i)
11151                                         decalsystem->freedecal = i;
11152                         }
11153                 }
11154         }
11155         decal = decalsystem->decals;
11156         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11157                 numdecals--;
11158
11159         // collapse the array by shuffling the tail decals into the gaps
11160         for (;;)
11161         {
11162                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11163                         decalsystem->freedecal++;
11164                 if (decalsystem->freedecal == numdecals)
11165                         break;
11166                 decal[decalsystem->freedecal] = decal[--numdecals];
11167         }
11168
11169         decalsystem->numdecals = numdecals;
11170
11171         if (numdecals <= 0)
11172         {
11173                 // if there are no decals left, reset decalsystem
11174                 R_DecalSystem_Reset(decalsystem);
11175         }
11176 }
11177
11178 extern skinframe_t *decalskinframe;
11179 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11180 {
11181         int i;
11182         decalsystem_t *decalsystem = &ent->decalsystem;
11183         int numdecals;
11184         tridecal_t *decal;
11185         float faderate;
11186         float alpha;
11187         float *v3f;
11188         float *c4f;
11189         float *t2f;
11190         const int *e;
11191         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11192         int numtris = 0;
11193
11194         numdecals = decalsystem->numdecals;
11195         if (!numdecals)
11196                 return;
11197
11198         if (r_showsurfaces.integer)
11199                 return;
11200
11201         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11202         {
11203                 R_DecalSystem_Reset(decalsystem);
11204                 return;
11205         }
11206
11207         // if the model is static it doesn't matter what value we give for
11208         // wantnormals and wanttangents, so this logic uses only rules applicable
11209         // to a model, knowing that they are meaningless otherwise
11210         if (ent == r_refdef.scene.worldentity)
11211                 RSurf_ActiveWorldEntity();
11212         else
11213                 RSurf_ActiveModelEntity(ent, false, false, false);
11214
11215         decalsystem->lastupdatetime = r_refdef.scene.time;
11216         decal = decalsystem->decals;
11217
11218         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11219
11220         // update vertex positions for animated models
11221         v3f = decalsystem->vertex3f;
11222         c4f = decalsystem->color4f;
11223         t2f = decalsystem->texcoord2f;
11224         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11225         {
11226                 if (!decal->color4f[0][3])
11227                         continue;
11228
11229                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11230                         continue;
11231
11232                 // skip backfaces
11233                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11234                         continue;
11235
11236                 // update color values for fading decals
11237                 if (decal->lived >= cl_decals_time.value)
11238                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11239                 else
11240                         alpha = 1.0f;
11241
11242                 c4f[ 0] = decal->color4f[0][0] * alpha;
11243                 c4f[ 1] = decal->color4f[0][1] * alpha;
11244                 c4f[ 2] = decal->color4f[0][2] * alpha;
11245                 c4f[ 3] = 1;
11246                 c4f[ 4] = decal->color4f[1][0] * alpha;
11247                 c4f[ 5] = decal->color4f[1][1] * alpha;
11248                 c4f[ 6] = decal->color4f[1][2] * alpha;
11249                 c4f[ 7] = 1;
11250                 c4f[ 8] = decal->color4f[2][0] * alpha;
11251                 c4f[ 9] = decal->color4f[2][1] * alpha;
11252                 c4f[10] = decal->color4f[2][2] * alpha;
11253                 c4f[11] = 1;
11254
11255                 t2f[0] = decal->texcoord2f[0][0];
11256                 t2f[1] = decal->texcoord2f[0][1];
11257                 t2f[2] = decal->texcoord2f[1][0];
11258                 t2f[3] = decal->texcoord2f[1][1];
11259                 t2f[4] = decal->texcoord2f[2][0];
11260                 t2f[5] = decal->texcoord2f[2][1];
11261
11262                 // update vertex positions for animated models
11263                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11264                 {
11265                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11266                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11267                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11268                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11269                 }
11270                 else
11271                 {
11272                         VectorCopy(decal->vertex3f[0], v3f);
11273                         VectorCopy(decal->vertex3f[1], v3f + 3);
11274                         VectorCopy(decal->vertex3f[2], v3f + 6);
11275                 }
11276
11277                 if (r_refdef.fogenabled)
11278                 {
11279                         alpha = RSurf_FogVertex(v3f);
11280                         VectorScale(c4f, alpha, c4f);
11281                         alpha = RSurf_FogVertex(v3f + 3);
11282                         VectorScale(c4f + 4, alpha, c4f + 4);
11283                         alpha = RSurf_FogVertex(v3f + 6);
11284                         VectorScale(c4f + 8, alpha, c4f + 8);
11285                 }
11286
11287                 v3f += 9;
11288                 c4f += 12;
11289                 t2f += 6;
11290                 numtris++;
11291         }
11292
11293         if (numtris > 0)
11294         {
11295                 r_refdef.stats.drawndecals += numtris;
11296
11297                 // now render the decals all at once
11298                 // (this assumes they all use one particle font texture!)
11299                 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);
11300 //              R_Mesh_ResetTextureState();
11301                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11302                 GL_DepthMask(false);
11303                 GL_DepthRange(0, 1);
11304                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11305                 GL_DepthTest(true);
11306                 GL_CullFace(GL_NONE);
11307                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11308                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11309                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11310         }
11311 }
11312
11313 static void R_DrawModelDecals(void)
11314 {
11315         int i, numdecals;
11316
11317         // fade faster when there are too many decals
11318         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11319         for (i = 0;i < r_refdef.scene.numentities;i++)
11320                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11321
11322         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11323         for (i = 0;i < r_refdef.scene.numentities;i++)
11324                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11325                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11326
11327         R_DecalSystem_ApplySplatEntitiesQueue();
11328
11329         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11330         for (i = 0;i < r_refdef.scene.numentities;i++)
11331                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11332
11333         r_refdef.stats.totaldecals += numdecals;
11334
11335         if (r_showsurfaces.integer)
11336                 return;
11337
11338         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11339
11340         for (i = 0;i < r_refdef.scene.numentities;i++)
11341         {
11342                 if (!r_refdef.viewcache.entityvisible[i])
11343                         continue;
11344                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11345                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11346         }
11347 }
11348
11349 extern cvar_t mod_collision_bih;
11350 static void R_DrawDebugModel(void)
11351 {
11352         entity_render_t *ent = rsurface.entity;
11353         int i, j, k, l, flagsmask;
11354         const msurface_t *surface;
11355         dp_model_t *model = ent->model;
11356         vec3_t v;
11357
11358         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11359                 return;
11360
11361         if (r_showoverdraw.value > 0)
11362         {
11363                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11364                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11365                 R_SetupShader_Generic_NoTexture(false, false);
11366                 GL_DepthTest(false);
11367                 GL_DepthMask(false);
11368                 GL_DepthRange(0, 1);
11369                 GL_BlendFunc(GL_ONE, GL_ONE);
11370                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11371                 {
11372                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11373                                 continue;
11374                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11375                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11376                         {
11377                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11378                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11379                                 if (!rsurface.texture->currentlayers->depthmask)
11380                                         GL_Color(c, 0, 0, 1.0f);
11381                                 else if (ent == r_refdef.scene.worldentity)
11382                                         GL_Color(c, c, c, 1.0f);
11383                                 else
11384                                         GL_Color(0, c, 0, 1.0f);
11385                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11386                                 RSurf_DrawBatch();
11387                         }
11388                 }
11389                 rsurface.texture = NULL;
11390         }
11391
11392         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11393
11394 //      R_Mesh_ResetTextureState();
11395         R_SetupShader_Generic_NoTexture(false, false);
11396         GL_DepthRange(0, 1);
11397         GL_DepthTest(!r_showdisabledepthtest.integer);
11398         GL_DepthMask(false);
11399         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11400
11401         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11402         {
11403                 int triangleindex;
11404                 int bihleafindex;
11405                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11406                 const q3mbrush_t *brush;
11407                 const bih_t *bih = &model->collision_bih;
11408                 const bih_leaf_t *bihleaf;
11409                 float vertex3f[3][3];
11410                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11411                 cullbox = false;
11412                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11413                 {
11414                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11415                                 continue;
11416                         switch (bihleaf->type)
11417                         {
11418                         case BIH_BRUSH:
11419                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11420                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11421                                 {
11422                                         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);
11423                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11424                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11425                                 }
11426                                 break;
11427                         case BIH_COLLISIONTRIANGLE:
11428                                 triangleindex = bihleaf->itemindex;
11429                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11430                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11431                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11432                                 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);
11433                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11434                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11435                                 break;
11436                         case BIH_RENDERTRIANGLE:
11437                                 triangleindex = bihleaf->itemindex;
11438                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11439                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11440                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11441                                 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);
11442                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11443                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11444                                 break;
11445                         }
11446                 }
11447         }
11448
11449         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11450
11451 #ifndef USE_GLES2
11452         if (r_showtris.integer && qglPolygonMode)
11453         {
11454                 if (r_showdisabledepthtest.integer)
11455                 {
11456                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11457                         GL_DepthMask(false);
11458                 }
11459                 else
11460                 {
11461                         GL_BlendFunc(GL_ONE, GL_ZERO);
11462                         GL_DepthMask(true);
11463                 }
11464                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11465                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11466                 {
11467                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11468                                 continue;
11469                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11470                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11471                         {
11472                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11473                                 if (!rsurface.texture->currentlayers->depthmask)
11474                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11475                                 else if (ent == r_refdef.scene.worldentity)
11476                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11477                                 else
11478                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11479                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11480                                 RSurf_DrawBatch();
11481                         }
11482                 }
11483                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11484                 rsurface.texture = NULL;
11485         }
11486
11487         if (r_shownormals.value != 0 && qglBegin)
11488         {
11489                 if (r_showdisabledepthtest.integer)
11490                 {
11491                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11492                         GL_DepthMask(false);
11493                 }
11494                 else
11495                 {
11496                         GL_BlendFunc(GL_ONE, GL_ZERO);
11497                         GL_DepthMask(true);
11498                 }
11499                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11500                 {
11501                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11502                                 continue;
11503                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11504                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11505                         {
11506                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11507                                 qglBegin(GL_LINES);
11508                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11509                                 {
11510                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11511                                         {
11512                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11513                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11514                                                 qglVertex3f(v[0], v[1], v[2]);
11515                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11516                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11517                                                 qglVertex3f(v[0], v[1], v[2]);
11518                                         }
11519                                 }
11520                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11521                                 {
11522                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11523                                         {
11524                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11525                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11526                                                 qglVertex3f(v[0], v[1], v[2]);
11527                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11528                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11529                                                 qglVertex3f(v[0], v[1], v[2]);
11530                                         }
11531                                 }
11532                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11533                                 {
11534                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11535                                         {
11536                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11537                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11538                                                 qglVertex3f(v[0], v[1], v[2]);
11539                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11540                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11541                                                 qglVertex3f(v[0], v[1], v[2]);
11542                                         }
11543                                 }
11544                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11545                                 {
11546                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11547                                         {
11548                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11549                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11550                                                 qglVertex3f(v[0], v[1], v[2]);
11551                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11552                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11553                                                 qglVertex3f(v[0], v[1], v[2]);
11554                                         }
11555                                 }
11556                                 qglEnd();
11557                                 CHECKGLERROR
11558                         }
11559                 }
11560                 rsurface.texture = NULL;
11561         }
11562 #endif
11563 }
11564
11565 int r_maxsurfacelist = 0;
11566 const msurface_t **r_surfacelist = NULL;
11567 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11568 {
11569         int i, j, endj, flagsmask;
11570         dp_model_t *model = r_refdef.scene.worldmodel;
11571         msurface_t *surfaces;
11572         unsigned char *update;
11573         int numsurfacelist = 0;
11574         if (model == NULL)
11575                 return;
11576
11577         if (r_maxsurfacelist < model->num_surfaces)
11578         {
11579                 r_maxsurfacelist = model->num_surfaces;
11580                 if (r_surfacelist)
11581                         Mem_Free((msurface_t**)r_surfacelist);
11582                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11583         }
11584
11585         RSurf_ActiveWorldEntity();
11586
11587         surfaces = model->data_surfaces;
11588         update = model->brushq1.lightmapupdateflags;
11589
11590         // update light styles on this submodel
11591         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11592         {
11593                 model_brush_lightstyleinfo_t *style;
11594                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11595                 {
11596                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11597                         {
11598                                 int *list = style->surfacelist;
11599                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11600                                 for (j = 0;j < style->numsurfaces;j++)
11601                                         update[list[j]] = true;
11602                         }
11603                 }
11604         }
11605
11606         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11607
11608         if (debug)
11609         {
11610                 R_DrawDebugModel();
11611                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11612                 return;
11613         }
11614
11615         rsurface.lightmaptexture = NULL;
11616         rsurface.deluxemaptexture = NULL;
11617         rsurface.uselightmaptexture = false;
11618         rsurface.texture = NULL;
11619         rsurface.rtlight = NULL;
11620         numsurfacelist = 0;
11621         // add visible surfaces to draw list
11622         for (i = 0;i < model->nummodelsurfaces;i++)
11623         {
11624                 j = model->sortedmodelsurfaces[i];
11625                 if (r_refdef.viewcache.world_surfacevisible[j])
11626                         r_surfacelist[numsurfacelist++] = surfaces + j;
11627         }
11628         // update lightmaps if needed
11629         if (model->brushq1.firstrender)
11630         {
11631                 model->brushq1.firstrender = false;
11632                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11633                         if (update[j])
11634                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11635         }
11636         else if (update)
11637         {
11638                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11639                         if (r_refdef.viewcache.world_surfacevisible[j])
11640                                 if (update[j])
11641                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11642         }
11643         // don't do anything if there were no surfaces
11644         if (!numsurfacelist)
11645         {
11646                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11647                 return;
11648         }
11649         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11650
11651         // add to stats if desired
11652         if (r_speeds.integer && !skysurfaces && !depthonly)
11653         {
11654                 r_refdef.stats.world_surfaces += numsurfacelist;
11655                 for (j = 0;j < numsurfacelist;j++)
11656                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11657         }
11658
11659         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11660 }
11661
11662 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11663 {
11664         int i, j, endj, flagsmask;
11665         dp_model_t *model = ent->model;
11666         msurface_t *surfaces;
11667         unsigned char *update;
11668         int numsurfacelist = 0;
11669         if (model == NULL)
11670                 return;
11671
11672         if (r_maxsurfacelist < model->num_surfaces)
11673         {
11674                 r_maxsurfacelist = model->num_surfaces;
11675                 if (r_surfacelist)
11676                         Mem_Free((msurface_t **)r_surfacelist);
11677                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11678         }
11679
11680         // if the model is static it doesn't matter what value we give for
11681         // wantnormals and wanttangents, so this logic uses only rules applicable
11682         // to a model, knowing that they are meaningless otherwise
11683         if (ent == r_refdef.scene.worldentity)
11684                 RSurf_ActiveWorldEntity();
11685         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11686                 RSurf_ActiveModelEntity(ent, false, false, false);
11687         else if (prepass)
11688                 RSurf_ActiveModelEntity(ent, true, true, true);
11689         else if (depthonly)
11690         {
11691                 switch (vid.renderpath)
11692                 {
11693                 case RENDERPATH_GL20:
11694                 case RENDERPATH_D3D9:
11695                 case RENDERPATH_D3D10:
11696                 case RENDERPATH_D3D11:
11697                 case RENDERPATH_SOFT:
11698                 case RENDERPATH_GLES2:
11699                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11700                         break;
11701                 case RENDERPATH_GL11:
11702                 case RENDERPATH_GL13:
11703                 case RENDERPATH_GLES1:
11704                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11705                         break;
11706                 }
11707         }
11708         else
11709         {
11710                 switch (vid.renderpath)
11711                 {
11712                 case RENDERPATH_GL20:
11713                 case RENDERPATH_D3D9:
11714                 case RENDERPATH_D3D10:
11715                 case RENDERPATH_D3D11:
11716                 case RENDERPATH_SOFT:
11717                 case RENDERPATH_GLES2:
11718                         RSurf_ActiveModelEntity(ent, true, true, false);
11719                         break;
11720                 case RENDERPATH_GL11:
11721                 case RENDERPATH_GL13:
11722                 case RENDERPATH_GLES1:
11723                         RSurf_ActiveModelEntity(ent, true, false, false);
11724                         break;
11725                 }
11726         }
11727
11728         surfaces = model->data_surfaces;
11729         update = model->brushq1.lightmapupdateflags;
11730
11731         // update light styles
11732         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11733         {
11734                 model_brush_lightstyleinfo_t *style;
11735                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11736                 {
11737                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11738                         {
11739                                 int *list = style->surfacelist;
11740                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11741                                 for (j = 0;j < style->numsurfaces;j++)
11742                                         update[list[j]] = true;
11743                         }
11744                 }
11745         }
11746
11747         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11748
11749         if (debug)
11750         {
11751                 R_DrawDebugModel();
11752                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11753                 return;
11754         }
11755
11756         rsurface.lightmaptexture = NULL;
11757         rsurface.deluxemaptexture = NULL;
11758         rsurface.uselightmaptexture = false;
11759         rsurface.texture = NULL;
11760         rsurface.rtlight = NULL;
11761         numsurfacelist = 0;
11762         // add visible surfaces to draw list
11763         for (i = 0;i < model->nummodelsurfaces;i++)
11764                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11765         // don't do anything if there were no surfaces
11766         if (!numsurfacelist)
11767         {
11768                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11769                 return;
11770         }
11771         // update lightmaps if needed
11772         if (update)
11773         {
11774                 int updated = 0;
11775                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11776                 {
11777                         if (update[j])
11778                         {
11779                                 updated++;
11780                                 R_BuildLightMap(ent, surfaces + j);
11781                         }
11782                 }
11783         }
11784         if (update)
11785                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11786                         if (update[j])
11787                                 R_BuildLightMap(ent, surfaces + j);
11788         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11789
11790         // add to stats if desired
11791         if (r_speeds.integer && !skysurfaces && !depthonly)
11792         {
11793                 r_refdef.stats.entities_surfaces += numsurfacelist;
11794                 for (j = 0;j < numsurfacelist;j++)
11795                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11796         }
11797
11798         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11799 }
11800
11801 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11802 {
11803         static texture_t texture;
11804         static msurface_t surface;
11805         const msurface_t *surfacelist = &surface;
11806
11807         // fake enough texture and surface state to render this geometry
11808
11809         texture.update_lastrenderframe = -1; // regenerate this texture
11810         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11811         texture.currentskinframe = skinframe;
11812         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11813         texture.offsetmapping = OFFSETMAPPING_OFF;
11814         texture.offsetscale = 1;
11815         texture.specularscalemod = 1;
11816         texture.specularpowermod = 1;
11817
11818         surface.texture = &texture;
11819         surface.num_triangles = numtriangles;
11820         surface.num_firsttriangle = firsttriangle;
11821         surface.num_vertices = numvertices;
11822         surface.num_firstvertex = firstvertex;
11823
11824         // now render it
11825         rsurface.texture = R_GetCurrentTexture(surface.texture);
11826         rsurface.lightmaptexture = NULL;
11827         rsurface.deluxemaptexture = NULL;
11828         rsurface.uselightmaptexture = false;
11829         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11830 }
11831
11832 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)
11833 {
11834         static msurface_t surface;
11835         const msurface_t *surfacelist = &surface;
11836
11837         // fake enough texture and surface state to render this geometry
11838         surface.texture = texture;
11839         surface.num_triangles = numtriangles;
11840         surface.num_firsttriangle = firsttriangle;
11841         surface.num_vertices = numvertices;
11842         surface.num_firstvertex = firstvertex;
11843
11844         // now render it
11845         rsurface.texture = R_GetCurrentTexture(surface.texture);
11846         rsurface.lightmaptexture = NULL;
11847         rsurface.deluxemaptexture = NULL;
11848         rsurface.uselightmaptexture = false;
11849         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11850 }